summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane2019-03-22 18:56:05 +0000
committerTom Lane2019-03-22 18:56:12 +0000
commit734308a220729e4ececa3758bdcae39a335d55ea (patch)
treea05d6decc28230b7833eac133776f80522c4e443
parent09963cedced7ffb98a06298cc16305767fd2b4dd (diff)
Rearrange make_partitionedrel_pruneinfo to avoid work when we can't prune.
Postpone most of the effort of constructing PartitionedRelPruneInfos until after we have found out whether run-time pruning is needed at all. This costs very little duplicated effort (basically just an extra find_base_rel() call per partition) and saves quite a bit when we can't do run-time pruning. Also, merge the first loop (for building relid_subpart_map) into the second loop, since we don't need the map to be valid during that loop. Amit Langote Discussion: https://postgr.es/m/[email protected]
-rw-r--r--src/backend/partitioning/partprune.c108
1 files changed, 68 insertions, 40 deletions
diff --git a/src/backend/partitioning/partprune.c b/src/backend/partitioning/partprune.c
index 31e0164ea9..c7f3ca2a20 100644
--- a/src/backend/partitioning/partprune.c
+++ b/src/backend/partitioning/partprune.c
@@ -326,46 +326,43 @@ make_partitionedrel_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel,
int i;
/*
- * Construct a temporary array to map from planner relids to index of the
- * partitioned_rel. For convenience, we use 1-based indexes here, so that
- * zero can represent an un-filled array entry.
+ * Examine each partitioned rel, constructing a temporary array to map
+ * from planner relids to index of the partitioned rel, and building a
+ * PartitionedRelPruneInfo for each partitioned rel.
+ *
+ * In this phase we discover whether runtime pruning is needed at all; if
+ * not, we can avoid doing further work.
*/
relid_subpart_map = palloc0(sizeof(int) * root->simple_rel_array_size);
- /*
- * relid_subpart_map maps relid of a non-leaf partition to the index in
- * 'partitioned_rels' of that rel (which will also be the index in the
- * returned PartitionedRelPruneInfo list of the info for that partition).
- */
i = 1;
foreach(lc, partitioned_rels)
{
Index rti = lfirst_int(lc);
-
- Assert(rti < root->simple_rel_array_size);
- /* No duplicates please */
- Assert(relid_subpart_map[rti] == 0);
-
- relid_subpart_map[rti] = i++;
- }
-
- /* We now build a PartitionedRelPruneInfo for each partitioned rel */
- foreach(lc, partitioned_rels)
- {
- Index rti = lfirst_int(lc);
RelOptInfo *subpart = find_base_rel(root, rti);
PartitionedRelPruneInfo *pinfo;
- Bitmapset *present_parts;
- int nparts = subpart->nparts;
int partnatts = subpart->part_scheme->partnatts;
- int *subplan_map;
- int *subpart_map;
- Oid *relid_map;
List *partprunequal;
List *pruning_steps;
bool contradictory;
/*
+ * Fill the mapping array.
+ *
+ * relid_subpart_map maps relid of a non-leaf partition to the index
+ * in 'partitioned_rels' of that rel (which will also be the index in
+ * the returned PartitionedRelPruneInfo list of the info for that
+ * partition). We use 1-based indexes here, so that zero can
+ * represent an un-filled array entry.
+ */
+ Assert(rti < root->simple_rel_array_size);
+ /* No duplicates please */
+ Assert(relid_subpart_map[rti] == 0);
+ relid_subpart_map[rti] = i++;
+
+ /*
+ * Translate pruning qual, if necessary, for this partition.
+ *
* The first item in the list is the target partitioned relation.
*/
if (!targetpart)
@@ -411,6 +408,7 @@ make_partitionedrel_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel,
targetpart->relids);
}
+ /* Convert pruning qual to pruning steps. */
pruning_steps = gen_partprune_steps(subpart, partprunequal,
&contradictory);
@@ -428,6 +426,47 @@ make_partitionedrel_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel,
return NIL;
}
+ /* Begin constructing the PartitionedRelPruneInfo for this rel */
+ pinfo = makeNode(PartitionedRelPruneInfo);
+ pinfo->rtindex = rti;
+ pinfo->pruning_steps = pruning_steps;
+ /* Remaining fields will be filled in the next loop */
+
+ pinfolist = lappend(pinfolist, pinfo);
+
+ /*
+ * Determine which pruning types should be enabled at this level. This
+ * also records paramids relevant to pruning steps in 'pinfo'.
+ */
+ doruntimeprune |= analyze_partkey_exprs(pinfo, pruning_steps,
+ partnatts);
+ }
+
+ if (!doruntimeprune)
+ {
+ /* No run-time pruning required. */
+ pfree(relid_subpart_map);
+ return NIL;
+ }
+
+ /*
+ * Run-time pruning will be required, so initialize other information.
+ * That includes two maps -- one needed to convert partition indexes of
+ * leaf partitions to the indexes of their subplans in the subplan list,
+ * another needed to convert partition indexes of sub-partitioned
+ * partitions to the indexes of their PartitionedRelPruneInfo in the
+ * PartitionedRelPruneInfo list.
+ */
+ foreach(lc, pinfolist)
+ {
+ PartitionedRelPruneInfo *pinfo = lfirst(lc);
+ RelOptInfo *subpart = find_base_rel(root, pinfo->rtindex);
+ Bitmapset *present_parts;
+ int nparts = subpart->nparts;
+ int *subplan_map;
+ int *subpart_map;
+ Oid *relid_map;
+
/*
* Construct the subplan and subpart maps for this partitioning level.
* Here we convert to zero-based indexes, with -1 for empty entries.
@@ -459,30 +498,16 @@ make_partitionedrel_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel,
present_parts = bms_add_member(present_parts, i);
}
- pinfo = makeNode(PartitionedRelPruneInfo);
- pinfo->rtindex = rti;
- pinfo->pruning_steps = pruning_steps;
+ /* Record the maps and other information. */
pinfo->present_parts = present_parts;
pinfo->nparts = nparts;
pinfo->subplan_map = subplan_map;
pinfo->subpart_map = subpart_map;
pinfo->relid_map = relid_map;
-
- /* Determine which pruning types should be enabled at this level */
- doruntimeprune |= analyze_partkey_exprs(pinfo, pruning_steps,
- partnatts);
-
- pinfolist = lappend(pinfolist, pinfo);
}
pfree(relid_subpart_map);
- if (!doruntimeprune)
- {
- /* No run-time pruning required. */
- return NIL;
- }
-
*matchedsubplans = subplansfound;
return pinfolist;
@@ -2907,6 +2932,9 @@ pull_exec_paramids_walker(Node *node, Bitmapset **context)
*
* Returns true if any executor partition pruning should be attempted at this
* level. Also fills fields of *pinfo to record how to process each step.
+ *
+ * Note: when this is called, not much of *pinfo is valid; but that's OK
+ * since we only use it as an output area.
*/
static bool
analyze_partkey_exprs(PartitionedRelPruneInfo *pinfo, List *steps,