From 16fd07b7c8ffde7632ffa7b03e4595e1e08d7e06 Mon Sep 17 00:00:00 2001 From: amitlan Date: Fri, 27 May 2022 16:00:28 +0900 Subject: [PATCH v16 1/2] Move PartitioPruneInfo out of plan nodes into PlannedStmt The planner will now add a given PartitioPruneInfo to PlannedStmt.partPruneInfos instead of the Append/MergeAppend plan node to which it would be added until now and set an index field in the plan node that point to the list element. A later commit will make AcquireExecutorLocks() do the initial partition pruning to determine a minimal set of partitions to be locked to validate a plan tree and it will need to consult the PartitioPruneInfos referenced therein to do so. It would be better for the PartitioPruneInfos to be accessible directly than them having to be found individually by walking the plan tree, which can be done by simply iterative over PlannedStmt.partPruneInfos. --- src/backend/executor/execMain.c | 1 + src/backend/executor/execParallel.c | 1 + src/backend/executor/execPartition.c | 4 +- src/backend/executor/execUtils.c | 2 + src/backend/executor/nodeAppend.c | 4 +- src/backend/executor/nodeMergeAppend.c | 4 +- src/backend/nodes/copyfuncs.c | 5 +- src/backend/nodes/outfuncs.c | 7 ++- src/backend/nodes/readfuncs.c | 5 +- src/backend/optimizer/plan/createplan.c | 24 ++++----- src/backend/optimizer/plan/planner.c | 1 + src/backend/optimizer/plan/setrefs.c | 65 +++++++++++++------------ src/backend/partitioning/partprune.c | 18 ++++--- src/include/executor/execPartition.h | 3 +- src/include/nodes/execnodes.h | 2 + src/include/nodes/pathnodes.h | 6 +++ src/include/nodes/plannodes.h | 12 +++-- src/include/partitioning/partprune.h | 8 +-- 18 files changed, 104 insertions(+), 68 deletions(-) diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index ef2fd46092..72fc273524 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -825,6 +825,7 @@ InitPlan(QueryDesc *queryDesc, int eflags) ExecInitRangeTable(estate, rangeTable); estate->es_plannedstmt = plannedstmt; + estate->es_part_prune_infos = plannedstmt->partPruneInfos; /* * Next, build the ExecRowMark array from the PlanRowMark(s), if any. diff --git a/src/backend/executor/execParallel.c b/src/backend/executor/execParallel.c index f1fd7f7e8b..f73b8c2607 100644 --- a/src/backend/executor/execParallel.c +++ b/src/backend/executor/execParallel.c @@ -183,6 +183,7 @@ ExecSerializePlan(Plan *plan, EState *estate) pstmt->dependsOnRole = false; pstmt->parallelModeNeeded = false; pstmt->planTree = plan; + pstmt->partPruneInfos = estate->es_part_prune_infos; pstmt->rtable = estate->es_range_table; pstmt->resultRelations = NIL; pstmt->appendRelations = NIL; diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c index e03ea27299..b55cdd2580 100644 --- a/src/backend/executor/execPartition.c +++ b/src/backend/executor/execPartition.c @@ -1638,11 +1638,13 @@ adjust_partition_colnos_using_map(List *colnos, AttrMap *attrMap) PartitionPruneState * ExecInitPartitionPruning(PlanState *planstate, int n_total_subplans, - PartitionPruneInfo *pruneinfo, + int part_prune_index, Bitmapset **initially_valid_subplans) { PartitionPruneState *prunestate; EState *estate = planstate->state; + PartitionPruneInfo *pruneinfo = list_nth(estate->es_part_prune_infos, + part_prune_index); /* We may need an expression context to evaluate partition exprs */ ExecAssignExprContext(estate, planstate); diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c index 9df1f81ea8..f9c7976ff2 100644 --- a/src/backend/executor/execUtils.c +++ b/src/backend/executor/execUtils.c @@ -119,6 +119,8 @@ CreateExecutorState(void) estate->es_relations = NULL; estate->es_rowmarks = NULL; estate->es_plannedstmt = NULL; + estate->es_part_prune_infos = NIL; + estate->es_part_prune_result = NULL; estate->es_junkFilter = NULL; diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c index 357e10a1d7..c6f86a6510 100644 --- a/src/backend/executor/nodeAppend.c +++ b/src/backend/executor/nodeAppend.c @@ -134,7 +134,7 @@ ExecInitAppend(Append *node, EState *estate, int eflags) appendstate->as_begun = false; /* If run-time partition pruning is enabled, then set that up now */ - if (node->part_prune_info != NULL) + if (node->part_prune_index >= 0) { PartitionPruneState *prunestate; @@ -145,7 +145,7 @@ ExecInitAppend(Append *node, EState *estate, int eflags) */ prunestate = ExecInitPartitionPruning(&appendstate->ps, list_length(node->appendplans), - node->part_prune_info, + node->part_prune_index, &validsubplans); appendstate->as_prune_state = prunestate; nplans = bms_num_members(validsubplans); diff --git a/src/backend/executor/nodeMergeAppend.c b/src/backend/executor/nodeMergeAppend.c index c5c62fa5c7..8d35860c30 100644 --- a/src/backend/executor/nodeMergeAppend.c +++ b/src/backend/executor/nodeMergeAppend.c @@ -82,7 +82,7 @@ ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags) mergestate->ps.ExecProcNode = ExecMergeAppend; /* If run-time partition pruning is enabled, then set that up now */ - if (node->part_prune_info != NULL) + if (node->part_prune_index >= 0) { PartitionPruneState *prunestate; @@ -93,7 +93,7 @@ ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags) */ prunestate = ExecInitPartitionPruning(&mergestate->ps, list_length(node->mergeplans), - node->part_prune_info, + node->part_prune_index, &validsubplans); mergestate->ms_prune_state = prunestate; nplans = bms_num_members(validsubplans); diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 51d630fa89..8fbeaa4f36 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -96,6 +96,7 @@ _copyPlannedStmt(const PlannedStmt *from) COPY_SCALAR_FIELD(parallelModeNeeded); COPY_SCALAR_FIELD(jitFlags); COPY_NODE_FIELD(planTree); + COPY_NODE_FIELD(partPruneInfos); COPY_NODE_FIELD(rtable); COPY_NODE_FIELD(resultRelations); COPY_NODE_FIELD(appendRelations); @@ -253,7 +254,7 @@ _copyAppend(const Append *from) COPY_NODE_FIELD(appendplans); COPY_SCALAR_FIELD(nasyncplans); COPY_SCALAR_FIELD(first_partial_plan); - COPY_NODE_FIELD(part_prune_info); + COPY_SCALAR_FIELD(part_prune_index); return newnode; } @@ -281,7 +282,7 @@ _copyMergeAppend(const MergeAppend *from) COPY_POINTER_FIELD(sortOperators, from->numCols * sizeof(Oid)); COPY_POINTER_FIELD(collations, from->numCols * sizeof(Oid)); COPY_POINTER_FIELD(nullsFirst, from->numCols * sizeof(bool)); - COPY_NODE_FIELD(part_prune_info); + COPY_SCALAR_FIELD(part_prune_index); return newnode; } diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index ce12915592..72fcd8a6ee 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -321,6 +321,7 @@ _outPlannedStmt(StringInfo str, const PlannedStmt *node) WRITE_BOOL_FIELD(parallelModeNeeded); WRITE_INT_FIELD(jitFlags); WRITE_NODE_FIELD(planTree); + WRITE_NODE_FIELD(partPruneInfos); WRITE_NODE_FIELD(rtable); WRITE_NODE_FIELD(resultRelations); WRITE_NODE_FIELD(appendRelations); @@ -450,7 +451,7 @@ _outAppend(StringInfo str, const Append *node) WRITE_NODE_FIELD(appendplans); WRITE_INT_FIELD(nasyncplans); WRITE_INT_FIELD(first_partial_plan); - WRITE_NODE_FIELD(part_prune_info); + WRITE_INT_FIELD(part_prune_index); } static void @@ -467,7 +468,7 @@ _outMergeAppend(StringInfo str, const MergeAppend *node) WRITE_OID_ARRAY(sortOperators, node->numCols); WRITE_OID_ARRAY(collations, node->numCols); WRITE_BOOL_ARRAY(nullsFirst, node->numCols); - WRITE_NODE_FIELD(part_prune_info); + WRITE_INT_FIELD(part_prune_index); } static void @@ -2434,6 +2435,7 @@ _outPlannerGlobal(StringInfo str, const PlannerGlobal *node) WRITE_NODE_FIELD(finalrowmarks); WRITE_NODE_FIELD(resultRelations); WRITE_NODE_FIELD(appendRelations); + WRITE_NODE_FIELD(partPruneInfos); WRITE_NODE_FIELD(relationOids); WRITE_NODE_FIELD(invalItems); WRITE_NODE_FIELD(paramExecTypes); @@ -2501,6 +2503,7 @@ _outPlannerInfo(StringInfo str, const PlannerInfo *node) WRITE_BITMAPSET_FIELD(curOuterRels); WRITE_NODE_FIELD(curOuterParams); WRITE_BOOL_FIELD(partColsUpdated); + WRITE_NODE_FIELD(partPruneInfos); } static void diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index 6a05b69415..bf602ff93e 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -1817,6 +1817,7 @@ _readPlannedStmt(void) READ_BOOL_FIELD(parallelModeNeeded); READ_INT_FIELD(jitFlags); READ_NODE_FIELD(planTree); + READ_NODE_FIELD(partPruneInfos); READ_NODE_FIELD(rtable); READ_NODE_FIELD(resultRelations); READ_NODE_FIELD(appendRelations); @@ -1949,7 +1950,7 @@ _readAppend(void) READ_NODE_FIELD(appendplans); READ_INT_FIELD(nasyncplans); READ_INT_FIELD(first_partial_plan); - READ_NODE_FIELD(part_prune_info); + READ_INT_FIELD(part_prune_index); READ_DONE(); } @@ -1971,7 +1972,7 @@ _readMergeAppend(void) READ_OID_ARRAY(sortOperators, local_node->numCols); READ_OID_ARRAY(collations, local_node->numCols); READ_BOOL_ARRAY(nullsFirst, local_node->numCols); - READ_NODE_FIELD(part_prune_info); + READ_INT_FIELD(part_prune_index); READ_DONE(); } diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 76606faa3e..58a05cf673 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -1203,7 +1203,6 @@ create_append_plan(PlannerInfo *root, AppendPath *best_path, int flags) ListCell *subpaths; int nasyncplans = 0; RelOptInfo *rel = best_path->path.parent; - PartitionPruneInfo *partpruneinfo = NULL; int nodenumsortkeys = 0; AttrNumber *nodeSortColIdx = NULL; Oid *nodeSortOperators = NULL; @@ -1354,6 +1353,9 @@ create_append_plan(PlannerInfo *root, AppendPath *best_path, int flags) subplans = lappend(subplans, subplan); } + /* Set below if we find quals that we can use to run-time prune */ + plan->part_prune_index = -1; + /* * If any quals exist, they may be useful to perform further partition * pruning during execution. Gather information needed by the executor to @@ -1377,16 +1379,14 @@ create_append_plan(PlannerInfo *root, AppendPath *best_path, int flags) } if (prunequal != NIL) - partpruneinfo = - make_partition_pruneinfo(root, rel, - best_path->subpaths, - prunequal); + plan->part_prune_index = make_partition_pruneinfo(root, rel, + best_path->subpaths, + prunequal); } plan->appendplans = subplans; plan->nasyncplans = nasyncplans; plan->first_partial_plan = best_path->first_partial_path; - plan->part_prune_info = partpruneinfo; copy_generic_path_info(&plan->plan, (Path *) best_path); @@ -1426,7 +1426,6 @@ create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path, List *subplans = NIL; ListCell *subpaths; RelOptInfo *rel = best_path->path.parent; - PartitionPruneInfo *partpruneinfo = NULL; /* * We don't have the actual creation of the MergeAppend node split out @@ -1519,6 +1518,9 @@ create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path, subplans = lappend(subplans, subplan); } + /* Set below if we find quals that we can use to run-time prune */ + node->part_prune_index = -1; + /* * If any quals exist, they may be useful to perform further partition * pruning during execution. Gather information needed by the executor to @@ -1542,13 +1544,13 @@ create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path, } if (prunequal != NIL) - partpruneinfo = make_partition_pruneinfo(root, rel, - best_path->subpaths, - prunequal); + node->part_prune_index = make_partition_pruneinfo(root, rel, + best_path->subpaths, + prunequal); } node->mergeplans = subplans; - node->part_prune_info = partpruneinfo; + /* * If prepare_sort_from_pathkeys added sort columns, but we were told to diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index a0f2390334..32e658b5d6 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -518,6 +518,7 @@ standard_planner(Query *parse, const char *query_string, int cursorOptions, result->dependsOnRole = glob->dependsOnRole; result->parallelModeNeeded = glob->parallelModeNeeded; result->planTree = top_plan; + result->partPruneInfos = glob->partPruneInfos; result->rtable = glob->finalrtable; result->resultRelations = glob->resultRelations; result->appendRelations = glob->appendRelations; diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index d95fd89807..aafe1c149d 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -348,6 +348,29 @@ set_plan_references(PlannerInfo *root, Plan *plan) } } + /* Also fix up the information in PartitionPruneInfos. */ + foreach (lc, root->partPruneInfos) + { + PartitionPruneInfo *pruneinfo = lfirst(lc); + ListCell *l; + + foreach(l, pruneinfo->prune_infos) + { + List *prune_infos = lfirst(l); + ListCell *l2; + + foreach(l2, prune_infos) + { + PartitionedRelPruneInfo *pinfo = lfirst(l2); + + /* RT index of the table to which the pinfo belongs. */ + pinfo->rtindex += rtoffset; + } + } + + glob->partPruneInfos = lappend(glob->partPruneInfos, pruneinfo); + } + return result; } @@ -1640,21 +1663,12 @@ set_append_references(PlannerInfo *root, aplan->apprelids = offset_relid_set(aplan->apprelids, rtoffset); - if (aplan->part_prune_info) - { - foreach(l, aplan->part_prune_info->prune_infos) - { - List *prune_infos = lfirst(l); - ListCell *l2; - - foreach(l2, prune_infos) - { - PartitionedRelPruneInfo *pinfo = lfirst(l2); - - pinfo->rtindex += rtoffset; - } - } - } + /* + * PartitionPruneInfos will be added to a list in PlannerGlobal, so update + * the index. + */ + if (aplan->part_prune_index >= 0) + aplan->part_prune_index += list_length(root->glob->partPruneInfos); /* We don't need to recurse to lefttree or righttree ... */ Assert(aplan->plan.lefttree == NULL); @@ -1712,21 +1726,12 @@ set_mergeappend_references(PlannerInfo *root, mplan->apprelids = offset_relid_set(mplan->apprelids, rtoffset); - if (mplan->part_prune_info) - { - foreach(l, mplan->part_prune_info->prune_infos) - { - List *prune_infos = lfirst(l); - ListCell *l2; - - foreach(l2, prune_infos) - { - PartitionedRelPruneInfo *pinfo = lfirst(l2); - - pinfo->rtindex += rtoffset; - } - } - } + /* + * PartitionPruneInfos will be added to a list in PlannerGlobal, so update + * the index. + */ + if (mplan->part_prune_index >= 0) + mplan->part_prune_index += list_length(root->glob->partPruneInfos); /* We don't need to recurse to lefttree or righttree ... */ Assert(mplan->plan.lefttree == NULL); diff --git a/src/backend/partitioning/partprune.c b/src/backend/partitioning/partprune.c index 9d3c05aed3..d77f7d3aef 100644 --- a/src/backend/partitioning/partprune.c +++ b/src/backend/partitioning/partprune.c @@ -209,16 +209,20 @@ static void partkey_datum_from_expr(PartitionPruneContext *context, /* * make_partition_pruneinfo - * Builds a PartitionPruneInfo which can be used in the executor to allow - * additional partition pruning to take place. Returns NULL when - * partition pruning would be useless. + * Checks if the given set of quals can be used to build pruning steps + * that the executor can use to prune away unneeded partitions. If + * suitable quals are found then a PartitionPruneInfo is built and tagged + * onto the PlannerInfo's partPruneInfos list. + * + * The return value is the 0-based index of the item added to the + * partPruneInfos list or -1 if nothing was added. * * 'parentrel' is the RelOptInfo for an appendrel, and 'subpaths' is the list * of scan paths for its child rels. * 'prunequal' is a list of potential pruning quals (i.e., restriction * clauses that are applicable to the appendrel). */ -PartitionPruneInfo * +int make_partition_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel, List *subpaths, List *prunequal) @@ -332,7 +336,7 @@ make_partition_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel, * quals, then we can just not bother with run-time pruning. */ if (prunerelinfos == NIL) - return NULL; + return -1; /* Else build the result data structure */ pruneinfo = makeNode(PartitionPruneInfo); @@ -358,7 +362,9 @@ make_partition_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel, else pruneinfo->other_subplans = NULL; - return pruneinfo; + root->partPruneInfos = lappend(root->partPruneInfos, pruneinfo); + + return list_length(root->partPruneInfos) - 1; } /* diff --git a/src/include/executor/execPartition.h b/src/include/executor/execPartition.h index 708435e952..bf962af7af 100644 --- a/src/include/executor/execPartition.h +++ b/src/include/executor/execPartition.h @@ -123,9 +123,8 @@ typedef struct PartitionPruneState extern PartitionPruneState *ExecInitPartitionPruning(PlanState *planstate, int n_total_subplans, - PartitionPruneInfo *pruneinfo, + int part_prune_index, Bitmapset **initially_valid_subplans); extern Bitmapset *ExecFindMatchingSubPlans(PartitionPruneState *prunestate, bool initial_prune); - #endif /* EXECPARTITION_H */ diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index 5728801379..25e0bb976e 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -596,6 +596,8 @@ typedef struct EState struct ExecRowMark **es_rowmarks; /* Array of per-range-table-entry * ExecRowMarks, or NULL if none */ PlannedStmt *es_plannedstmt; /* link to top of plan tree */ + List *es_part_prune_infos; /* PlannedStmt.partPruneInfos */ + struct PartitionPruneResult *es_part_prune_result; /* QueryDesc.part_prune_result */ const char *es_sourceText; /* Source text from QueryDesc */ JunkFilter *es_junkFilter; /* top-level junk filter, if any */ diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index a6e5db4eec..6995b0ecec 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -107,6 +107,9 @@ typedef struct PlannerGlobal List *appendRelations; /* "flat" list of AppendRelInfos */ + List *partPruneInfos; /* List of PartitionPruneInfo contained in + * the plan */ + List *relationOids; /* OIDs of relations the plan depends on */ List *invalItems; /* other dependencies, as PlanInvalItems */ @@ -378,6 +381,9 @@ struct PlannerInfo /* Does this query modify any partition key columns? */ bool partColsUpdated; + + /* PartitionPruneInfos added in this query's plan. */ + List *partPruneInfos; }; diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index 0ea9a22dfb..297cacfb5b 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -64,6 +64,9 @@ typedef struct PlannedStmt struct Plan *planTree; /* tree of Plan nodes */ + List *partPruneInfos; /* List of PartitionPruneInfo contained in + * the plan */ + List *rtable; /* list of RangeTblEntry nodes */ /* rtable indexes of target relations for INSERT/UPDATE/DELETE */ @@ -262,8 +265,8 @@ typedef struct Append */ int first_partial_plan; - /* Info for run-time subplan pruning; NULL if we're not doing that */ - struct PartitionPruneInfo *part_prune_info; + /* Index to PlannerInfo.partPruneInfos or -1 if no run-time pruning */ + int part_prune_index; } Append; /* ---------------- @@ -282,8 +285,9 @@ typedef struct MergeAppend Oid *sortOperators; /* OIDs of operators to sort them by */ Oid *collations; /* OIDs of collations */ bool *nullsFirst; /* NULLS FIRST/LAST directions */ - /* Info for run-time subplan pruning; NULL if we're not doing that */ - struct PartitionPruneInfo *part_prune_info; + + /* Index to PlannerInfo.partPruneInfos or -1 if no run-time pruning */ + int part_prune_index; } MergeAppend; /* ---------------- diff --git a/src/include/partitioning/partprune.h b/src/include/partitioning/partprune.h index 90684efa25..ebf0dcff8c 100644 --- a/src/include/partitioning/partprune.h +++ b/src/include/partitioning/partprune.h @@ -70,10 +70,10 @@ typedef struct PartitionPruneContext #define PruneCxtStateIdx(partnatts, step_id, keyno) \ ((partnatts) * (step_id) + (keyno)) -extern PartitionPruneInfo *make_partition_pruneinfo(struct PlannerInfo *root, - struct RelOptInfo *parentrel, - List *subpaths, - List *prunequal); +extern int make_partition_pruneinfo(struct PlannerInfo *root, + struct RelOptInfo *parentrel, + List *subpaths, + List *prunequal); extern Bitmapset *prune_append_rel_partitions(struct RelOptInfo *rel); extern Bitmapset *get_matching_partitions(PartitionPruneContext *context, List *pruning_steps); -- 2.35.3