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/9d7c5112-cb99-6a47-d3be-cf1ee6862a1d@lab.ntt.co.jp
This commit is contained in:
parent
09963cedce
commit
734308a220
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user