Skip to content

Commit 734308a

Browse files
committed
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
1 parent 09963ce commit 734308a

File tree

1 file changed

+68
-40
lines changed

1 file changed

+68
-40
lines changed

src/backend/partitioning/partprune.c

Lines changed: 68 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -326,46 +326,43 @@ make_partitionedrel_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel,
326326
int i;
327327

328328
/*
329-
* Construct a temporary array to map from planner relids to index of the
330-
* partitioned_rel. For convenience, we use 1-based indexes here, so that
331-
* zero can represent an un-filled array entry.
329+
* Examine each partitioned rel, constructing a temporary array to map
330+
* from planner relids to index of the partitioned rel, and building a
331+
* PartitionedRelPruneInfo for each partitioned rel.
332+
*
333+
* In this phase we discover whether runtime pruning is needed at all; if
334+
* not, we can avoid doing further work.
332335
*/
333336
relid_subpart_map = palloc0(sizeof(int) * root->simple_rel_array_size);
334337

335-
/*
336-
* relid_subpart_map maps relid of a non-leaf partition to the index in
337-
* 'partitioned_rels' of that rel (which will also be the index in the
338-
* returned PartitionedRelPruneInfo list of the info for that partition).
339-
*/
340338
i = 1;
341339
foreach(lc, partitioned_rels)
342-
{
343-
Index rti = lfirst_int(lc);
344-
345-
Assert(rti < root->simple_rel_array_size);
346-
/* No duplicates please */
347-
Assert(relid_subpart_map[rti] == 0);
348-
349-
relid_subpart_map[rti] = i++;
350-
}
351-
352-
/* We now build a PartitionedRelPruneInfo for each partitioned rel */
353-
foreach(lc, partitioned_rels)
354340
{
355341
Index rti = lfirst_int(lc);
356342
RelOptInfo *subpart = find_base_rel(root, rti);
357343
PartitionedRelPruneInfo *pinfo;
358-
Bitmapset *present_parts;
359-
int nparts = subpart->nparts;
360344
int partnatts = subpart->part_scheme->partnatts;
361-
int *subplan_map;
362-
int *subpart_map;
363-
Oid *relid_map;
364345
List *partprunequal;
365346
List *pruning_steps;
366347
bool contradictory;
367348

368349
/*
350+
* Fill the mapping array.
351+
*
352+
* relid_subpart_map maps relid of a non-leaf partition to the index
353+
* in 'partitioned_rels' of that rel (which will also be the index in
354+
* the returned PartitionedRelPruneInfo list of the info for that
355+
* partition). We use 1-based indexes here, so that zero can
356+
* represent an un-filled array entry.
357+
*/
358+
Assert(rti < root->simple_rel_array_size);
359+
/* No duplicates please */
360+
Assert(relid_subpart_map[rti] == 0);
361+
relid_subpart_map[rti] = i++;
362+
363+
/*
364+
* Translate pruning qual, if necessary, for this partition.
365+
*
369366
* The first item in the list is the target partitioned relation.
370367
*/
371368
if (!targetpart)
@@ -411,6 +408,7 @@ make_partitionedrel_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel,
411408
targetpart->relids);
412409
}
413410

411+
/* Convert pruning qual to pruning steps. */
414412
pruning_steps = gen_partprune_steps(subpart, partprunequal,
415413
&contradictory);
416414

@@ -428,6 +426,47 @@ make_partitionedrel_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel,
428426
return NIL;
429427
}
430428

429+
/* Begin constructing the PartitionedRelPruneInfo for this rel */
430+
pinfo = makeNode(PartitionedRelPruneInfo);
431+
pinfo->rtindex = rti;
432+
pinfo->pruning_steps = pruning_steps;
433+
/* Remaining fields will be filled in the next loop */
434+
435+
pinfolist = lappend(pinfolist, pinfo);
436+
437+
/*
438+
* Determine which pruning types should be enabled at this level. This
439+
* also records paramids relevant to pruning steps in 'pinfo'.
440+
*/
441+
doruntimeprune |= analyze_partkey_exprs(pinfo, pruning_steps,
442+
partnatts);
443+
}
444+
445+
if (!doruntimeprune)
446+
{
447+
/* No run-time pruning required. */
448+
pfree(relid_subpart_map);
449+
return NIL;
450+
}
451+
452+
/*
453+
* Run-time pruning will be required, so initialize other information.
454+
* That includes two maps -- one needed to convert partition indexes of
455+
* leaf partitions to the indexes of their subplans in the subplan list,
456+
* another needed to convert partition indexes of sub-partitioned
457+
* partitions to the indexes of their PartitionedRelPruneInfo in the
458+
* PartitionedRelPruneInfo list.
459+
*/
460+
foreach(lc, pinfolist)
461+
{
462+
PartitionedRelPruneInfo *pinfo = lfirst(lc);
463+
RelOptInfo *subpart = find_base_rel(root, pinfo->rtindex);
464+
Bitmapset *present_parts;
465+
int nparts = subpart->nparts;
466+
int *subplan_map;
467+
int *subpart_map;
468+
Oid *relid_map;
469+
431470
/*
432471
* Construct the subplan and subpart maps for this partitioning level.
433472
* Here we convert to zero-based indexes, with -1 for empty entries.
@@ -459,30 +498,16 @@ make_partitionedrel_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel,
459498
present_parts = bms_add_member(present_parts, i);
460499
}
461500

462-
pinfo = makeNode(PartitionedRelPruneInfo);
463-
pinfo->rtindex = rti;
464-
pinfo->pruning_steps = pruning_steps;
501+
/* Record the maps and other information. */
465502
pinfo->present_parts = present_parts;
466503
pinfo->nparts = nparts;
467504
pinfo->subplan_map = subplan_map;
468505
pinfo->subpart_map = subpart_map;
469506
pinfo->relid_map = relid_map;
470-
471-
/* Determine which pruning types should be enabled at this level */
472-
doruntimeprune |= analyze_partkey_exprs(pinfo, pruning_steps,
473-
partnatts);
474-
475-
pinfolist = lappend(pinfolist, pinfo);
476507
}
477508

478509
pfree(relid_subpart_map);
479510

480-
if (!doruntimeprune)
481-
{
482-
/* No run-time pruning required. */
483-
return NIL;
484-
}
485-
486511
*matchedsubplans = subplansfound;
487512

488513
return pinfolist;
@@ -2907,6 +2932,9 @@ pull_exec_paramids_walker(Node *node, Bitmapset **context)
29072932
*
29082933
* Returns true if any executor partition pruning should be attempted at this
29092934
* level. Also fills fields of *pinfo to record how to process each step.
2935+
*
2936+
* Note: when this is called, not much of *pinfo is valid; but that's OK
2937+
* since we only use it as an output area.
29102938
*/
29112939
static bool
29122940
analyze_partkey_exprs(PartitionedRelPruneInfo *pinfo, List *steps,

0 commit comments

Comments
 (0)