1
0
mirror of https://github.com/postgres/postgres.git synced 2025-04-21 12:05:57 +03:00

Move PartitioPruneInfo out of plan nodes into PlannedStmt

The planner will now add a given PartitioPruneInfo to
PlannedStmt.partPruneInfos instead of directly to the
Append/MergeAppend plan node.  What gets set instead in the
latter is an index field which points to the list element
of PlannedStmt.partPruneInfos containing the PartitioPruneInfo
belonging to the plan node.

A later commit will make AcquireExecutorLocks() do the initial
partition pruning to determine a minimal set of partitions to be
locked when validating 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 requiring
a walk of the plan tree to find them, which is easier when it can be
done by simply iterating over PlannedStmt.partPruneInfos.

Author: Amit Langote <amitlangote09@gmail.com>
Discussion: https://postgr.es/m/CA+HiwqFGkMSge6TgC9KQzde0ohpAycLQuV7ooitEEpbKB0O_mg@mail.gmail.com
This commit is contained in:
Alvaro Herrera 2022-12-01 12:56:21 +01:00
parent de867c9c53
commit ec38694894
No known key found for this signature in database
GPG Key ID: 1C20ACB9D5C564AE
16 changed files with 114 additions and 63 deletions

View File

@ -825,6 +825,7 @@ InitPlan(QueryDesc *queryDesc, int eflags)
ExecInitRangeTable(estate, rangeTable); ExecInitRangeTable(estate, rangeTable);
estate->es_plannedstmt = plannedstmt; estate->es_plannedstmt = plannedstmt;
estate->es_part_prune_infos = plannedstmt->partPruneInfos;
/* /*
* Next, build the ExecRowMark array from the PlanRowMark(s), if any. * Next, build the ExecRowMark array from the PlanRowMark(s), if any.

View File

@ -183,6 +183,7 @@ ExecSerializePlan(Plan *plan, EState *estate)
pstmt->dependsOnRole = false; pstmt->dependsOnRole = false;
pstmt->parallelModeNeeded = false; pstmt->parallelModeNeeded = false;
pstmt->planTree = plan; pstmt->planTree = plan;
pstmt->partPruneInfos = estate->es_part_prune_infos;
pstmt->rtable = estate->es_range_table; pstmt->rtable = estate->es_range_table;
pstmt->resultRelations = NIL; pstmt->resultRelations = NIL;
pstmt->appendRelations = NIL; pstmt->appendRelations = NIL;

View File

@ -1791,6 +1791,9 @@ adjust_partition_colnos_using_map(List *colnos, AttrMap *attrMap)
* Initialize data structure needed for run-time partition pruning and * Initialize data structure needed for run-time partition pruning and
* do initial pruning if needed * do initial pruning if needed
* *
* 'root_parent_relids' identifies the relation to which both the parent plan
* and the PartitionPruneInfo given by 'part_prune_index' belong.
*
* On return, *initially_valid_subplans is assigned the set of indexes of * On return, *initially_valid_subplans is assigned the set of indexes of
* child subplans that must be initialized along with the parent plan node. * child subplans that must be initialized along with the parent plan node.
* Initial pruning is performed here if needed and in that case only the * Initial pruning is performed here if needed and in that case only the
@ -1803,11 +1806,24 @@ adjust_partition_colnos_using_map(List *colnos, AttrMap *attrMap)
PartitionPruneState * PartitionPruneState *
ExecInitPartitionPruning(PlanState *planstate, ExecInitPartitionPruning(PlanState *planstate,
int n_total_subplans, int n_total_subplans,
PartitionPruneInfo *pruneinfo, int part_prune_index,
Bitmapset *root_parent_relids,
Bitmapset **initially_valid_subplans) Bitmapset **initially_valid_subplans)
{ {
PartitionPruneState *prunestate; PartitionPruneState *prunestate;
EState *estate = planstate->state; EState *estate = planstate->state;
PartitionPruneInfo *pruneinfo;
/* Obtain the pruneinfo we need, and make sure it's the right one */
pruneinfo = list_nth(estate->es_part_prune_infos, part_prune_index);
if (!bms_equal(root_parent_relids, pruneinfo->root_parent_relids))
ereport(ERROR,
errcode(ERRCODE_INTERNAL_ERROR),
errmsg_internal("mismatching PartitionPruneInfo found at part_prune_index %d",
part_prune_index),
errdetail_internal("plan node relids %s, pruneinfo relids %s",
bmsToString(root_parent_relids),
bmsToString(pruneinfo->root_parent_relids)));
/* We may need an expression context to evaluate partition exprs */ /* We may need an expression context to evaluate partition exprs */
ExecAssignExprContext(estate, planstate); ExecAssignExprContext(estate, planstate);

View File

@ -119,6 +119,7 @@ CreateExecutorState(void)
estate->es_relations = NULL; estate->es_relations = NULL;
estate->es_rowmarks = NULL; estate->es_rowmarks = NULL;
estate->es_plannedstmt = NULL; estate->es_plannedstmt = NULL;
estate->es_part_prune_infos = NIL;
estate->es_junkFilter = NULL; estate->es_junkFilter = NULL;

View File

@ -134,7 +134,7 @@ ExecInitAppend(Append *node, EState *estate, int eflags)
appendstate->as_begun = false; appendstate->as_begun = false;
/* If run-time partition pruning is enabled, then set that up now */ /* 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; PartitionPruneState *prunestate;
@ -145,7 +145,8 @@ ExecInitAppend(Append *node, EState *estate, int eflags)
*/ */
prunestate = ExecInitPartitionPruning(&appendstate->ps, prunestate = ExecInitPartitionPruning(&appendstate->ps,
list_length(node->appendplans), list_length(node->appendplans),
node->part_prune_info, node->part_prune_index,
node->apprelids,
&validsubplans); &validsubplans);
appendstate->as_prune_state = prunestate; appendstate->as_prune_state = prunestate;
nplans = bms_num_members(validsubplans); nplans = bms_num_members(validsubplans);

View File

@ -82,7 +82,7 @@ ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags)
mergestate->ps.ExecProcNode = ExecMergeAppend; mergestate->ps.ExecProcNode = ExecMergeAppend;
/* If run-time partition pruning is enabled, then set that up now */ /* 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; PartitionPruneState *prunestate;
@ -93,7 +93,8 @@ ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags)
*/ */
prunestate = ExecInitPartitionPruning(&mergestate->ps, prunestate = ExecInitPartitionPruning(&mergestate->ps,
list_length(node->mergeplans), list_length(node->mergeplans),
node->part_prune_info, node->part_prune_index,
node->apprelids,
&validsubplans); &validsubplans);
mergestate->ms_prune_state = prunestate; mergestate->ms_prune_state = prunestate;
nplans = bms_num_members(validsubplans); nplans = bms_num_members(validsubplans);

View File

@ -1203,7 +1203,6 @@ create_append_plan(PlannerInfo *root, AppendPath *best_path, int flags)
ListCell *subpaths; ListCell *subpaths;
int nasyncplans = 0; int nasyncplans = 0;
RelOptInfo *rel = best_path->path.parent; RelOptInfo *rel = best_path->path.parent;
PartitionPruneInfo *partpruneinfo = NULL;
int nodenumsortkeys = 0; int nodenumsortkeys = 0;
AttrNumber *nodeSortColIdx = NULL; AttrNumber *nodeSortColIdx = NULL;
Oid *nodeSortOperators = NULL; Oid *nodeSortOperators = NULL;
@ -1354,6 +1353,9 @@ create_append_plan(PlannerInfo *root, AppendPath *best_path, int flags)
subplans = lappend(subplans, subplan); 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 * If any quals exist, they may be useful to perform further partition
* pruning during execution. Gather information needed by the executor to * pruning during execution. Gather information needed by the executor to
@ -1377,8 +1379,7 @@ create_append_plan(PlannerInfo *root, AppendPath *best_path, int flags)
} }
if (prunequal != NIL) if (prunequal != NIL)
partpruneinfo = plan->part_prune_index = make_partition_pruneinfo(root, rel,
make_partition_pruneinfo(root, rel,
best_path->subpaths, best_path->subpaths,
prunequal); prunequal);
} }
@ -1386,7 +1387,6 @@ create_append_plan(PlannerInfo *root, AppendPath *best_path, int flags)
plan->appendplans = subplans; plan->appendplans = subplans;
plan->nasyncplans = nasyncplans; plan->nasyncplans = nasyncplans;
plan->first_partial_plan = best_path->first_partial_path; plan->first_partial_plan = best_path->first_partial_path;
plan->part_prune_info = partpruneinfo;
copy_generic_path_info(&plan->plan, (Path *) best_path); copy_generic_path_info(&plan->plan, (Path *) best_path);
@ -1425,7 +1425,6 @@ create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path,
List *subplans = NIL; List *subplans = NIL;
ListCell *subpaths; ListCell *subpaths;
RelOptInfo *rel = best_path->path.parent; RelOptInfo *rel = best_path->path.parent;
PartitionPruneInfo *partpruneinfo = NULL;
/* /*
* We don't have the actual creation of the MergeAppend node split out * We don't have the actual creation of the MergeAppend node split out
@ -1518,6 +1517,9 @@ create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path,
subplans = lappend(subplans, subplan); 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 * If any quals exist, they may be useful to perform further partition
* pruning during execution. Gather information needed by the executor to * pruning during execution. Gather information needed by the executor to
@ -1541,13 +1543,13 @@ create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path,
} }
if (prunequal != NIL) if (prunequal != NIL)
partpruneinfo = make_partition_pruneinfo(root, rel, node->part_prune_index = make_partition_pruneinfo(root, rel,
best_path->subpaths, best_path->subpaths,
prunequal); prunequal);
} }
node->mergeplans = subplans; node->mergeplans = subplans;
node->part_prune_info = partpruneinfo;
/* /*
* If prepare_sort_from_pathkeys added sort columns, but we were told to * If prepare_sort_from_pathkeys added sort columns, but we were told to

View File

@ -519,6 +519,7 @@ standard_planner(Query *parse, const char *query_string, int cursorOptions,
result->dependsOnRole = glob->dependsOnRole; result->dependsOnRole = glob->dependsOnRole;
result->parallelModeNeeded = glob->parallelModeNeeded; result->parallelModeNeeded = glob->parallelModeNeeded;
result->planTree = top_plan; result->planTree = top_plan;
result->partPruneInfos = glob->partPruneInfos;
result->rtable = glob->finalrtable; result->rtable = glob->finalrtable;
result->resultRelations = glob->resultRelations; result->resultRelations = glob->resultRelations;
result->appendRelations = glob->appendRelations; result->appendRelations = glob->appendRelations;

View File

@ -348,6 +348,31 @@ set_plan_references(PlannerInfo *root, Plan *plan)
} }
} }
/* Also fix up the information in PartitionPruneInfos. */
foreach (lc, root->partPruneInfos)
{
PartitionPruneInfo *pruneinfo = lfirst(lc);
ListCell *l;
pruneinfo->root_parent_relids =
offset_relid_set(pruneinfo->root_parent_relids, rtoffset);
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; return result;
} }
@ -1658,21 +1683,12 @@ set_append_references(PlannerInfo *root,
aplan->apprelids = offset_relid_set(aplan->apprelids, rtoffset); aplan->apprelids = offset_relid_set(aplan->apprelids, rtoffset);
if (aplan->part_prune_info) /*
{ * PartitionPruneInfos will be added to a list in PlannerGlobal, so update
foreach(l, aplan->part_prune_info->prune_infos) * the index.
{ */
List *prune_infos = lfirst(l); if (aplan->part_prune_index >= 0)
ListCell *l2; aplan->part_prune_index += list_length(root->glob->partPruneInfos);
foreach(l2, prune_infos)
{
PartitionedRelPruneInfo *pinfo = lfirst(l2);
pinfo->rtindex += rtoffset;
}
}
}
/* We don't need to recurse to lefttree or righttree ... */ /* We don't need to recurse to lefttree or righttree ... */
Assert(aplan->plan.lefttree == NULL); Assert(aplan->plan.lefttree == NULL);
@ -1734,21 +1750,12 @@ set_mergeappend_references(PlannerInfo *root,
mplan->apprelids = offset_relid_set(mplan->apprelids, rtoffset); mplan->apprelids = offset_relid_set(mplan->apprelids, rtoffset);
if (mplan->part_prune_info) /*
{ * PartitionPruneInfos will be added to a list in PlannerGlobal, so update
foreach(l, mplan->part_prune_info->prune_infos) * the index.
{ */
List *prune_infos = lfirst(l); if (mplan->part_prune_index >= 0)
ListCell *l2; mplan->part_prune_index += list_length(root->glob->partPruneInfos);
foreach(l2, prune_infos)
{
PartitionedRelPruneInfo *pinfo = lfirst(l2);
pinfo->rtindex += rtoffset;
}
}
}
/* We don't need to recurse to lefttree or righttree ... */ /* We don't need to recurse to lefttree or righttree ... */
Assert(mplan->plan.lefttree == NULL); Assert(mplan->plan.lefttree == NULL);

View File

@ -209,16 +209,20 @@ static void partkey_datum_from_expr(PartitionPruneContext *context,
/* /*
* make_partition_pruneinfo * make_partition_pruneinfo
* Builds a PartitionPruneInfo which can be used in the executor to allow * Checks if the given set of quals can be used to build pruning steps
* additional partition pruning to take place. Returns NULL when * that the executor can use to prune away unneeded partitions. If
* partition pruning would be useless. * 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 * 'parentrel' is the RelOptInfo for an appendrel, and 'subpaths' is the list
* of scan paths for its child rels. * of scan paths for its child rels.
* 'prunequal' is a list of potential pruning quals (i.e., restriction * 'prunequal' is a list of potential pruning quals (i.e., restriction
* clauses that are applicable to the appendrel). * clauses that are applicable to the appendrel).
*/ */
PartitionPruneInfo * int
make_partition_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel, make_partition_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel,
List *subpaths, List *subpaths,
List *prunequal) List *prunequal)
@ -332,10 +336,11 @@ make_partition_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel,
* quals, then we can just not bother with run-time pruning. * quals, then we can just not bother with run-time pruning.
*/ */
if (prunerelinfos == NIL) if (prunerelinfos == NIL)
return NULL; return -1;
/* Else build the result data structure */ /* Else build the result data structure */
pruneinfo = makeNode(PartitionPruneInfo); pruneinfo = makeNode(PartitionPruneInfo);
pruneinfo->root_parent_relids = parentrel->relids;
pruneinfo->prune_infos = prunerelinfos; pruneinfo->prune_infos = prunerelinfos;
/* /*
@ -358,7 +363,9 @@ make_partition_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel,
else else
pruneinfo->other_subplans = NULL; pruneinfo->other_subplans = NULL;
return pruneinfo; root->partPruneInfos = lappend(root->partPruneInfos, pruneinfo);
return list_length(root->partPruneInfos) - 1;
} }
/* /*

View File

@ -57,6 +57,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 202211301 #define CATALOG_VERSION_NO 202212011
#endif #endif

View File

@ -123,9 +123,9 @@ typedef struct PartitionPruneState
extern PartitionPruneState *ExecInitPartitionPruning(PlanState *planstate, extern PartitionPruneState *ExecInitPartitionPruning(PlanState *planstate,
int n_total_subplans, int n_total_subplans,
PartitionPruneInfo *pruneinfo, int part_prune_index,
Bitmapset *root_parent_relids,
Bitmapset **initially_valid_subplans); Bitmapset **initially_valid_subplans);
extern Bitmapset *ExecFindMatchingSubPlans(PartitionPruneState *prunestate, extern Bitmapset *ExecFindMatchingSubPlans(PartitionPruneState *prunestate,
bool initial_prune); bool initial_prune);
#endif /* EXECPARTITION_H */ #endif /* EXECPARTITION_H */

View File

@ -614,6 +614,7 @@ typedef struct EState
struct ExecRowMark **es_rowmarks; /* Array of per-range-table-entry struct ExecRowMark **es_rowmarks; /* Array of per-range-table-entry
* ExecRowMarks, or NULL if none */ * ExecRowMarks, or NULL if none */
PlannedStmt *es_plannedstmt; /* link to top of plan tree */ PlannedStmt *es_plannedstmt; /* link to top of plan tree */
List *es_part_prune_infos; /* PlannedStmt.partPruneInfos */
const char *es_sourceText; /* Source text from QueryDesc */ const char *es_sourceText; /* Source text from QueryDesc */
JunkFilter *es_junkFilter; /* top-level junk filter, if any */ JunkFilter *es_junkFilter; /* top-level junk filter, if any */

View File

@ -122,6 +122,9 @@ typedef struct PlannerGlobal
/* "flat" list of AppendRelInfos */ /* "flat" list of AppendRelInfos */
List *appendRelations; List *appendRelations;
/* List of PartitionPruneInfo contained in the plan */
List *partPruneInfos;
/* OIDs of relations the plan depends on */ /* OIDs of relations the plan depends on */
List *relationOids; List *relationOids;
@ -503,6 +506,9 @@ struct PlannerInfo
/* Does this query modify any partition key columns? */ /* Does this query modify any partition key columns? */
bool partColsUpdated; bool partColsUpdated;
/* PartitionPruneInfos added in this query's plan. */
List *partPruneInfos;
}; };

View File

@ -70,6 +70,9 @@ typedef struct PlannedStmt
struct Plan *planTree; /* tree of Plan nodes */ struct Plan *planTree; /* tree of Plan nodes */
List *partPruneInfos; /* List of PartitionPruneInfo contained in
* the plan */
List *rtable; /* list of RangeTblEntry nodes */ List *rtable; /* list of RangeTblEntry nodes */
/* rtable indexes of target relations for INSERT/UPDATE/DELETE/MERGE */ /* rtable indexes of target relations for INSERT/UPDATE/DELETE/MERGE */
@ -270,8 +273,8 @@ typedef struct Append
*/ */
int first_partial_plan; int first_partial_plan;
/* Info for run-time subplan pruning; NULL if we're not doing that */ /* Index to PlannerInfo.partPruneInfos or -1 if no run-time pruning */
struct PartitionPruneInfo *part_prune_info; int part_prune_index;
} Append; } Append;
/* ---------------- /* ----------------
@ -305,8 +308,8 @@ typedef struct MergeAppend
/* NULLS FIRST/LAST directions */ /* NULLS FIRST/LAST directions */
bool *nullsFirst pg_node_attr(array_size(numCols)); bool *nullsFirst pg_node_attr(array_size(numCols));
/* Info for run-time subplan pruning; NULL if we're not doing that */ /* Index to PlannerInfo.partPruneInfos or -1 if no run-time pruning */
struct PartitionPruneInfo *part_prune_info; int part_prune_index;
} MergeAppend; } MergeAppend;
/* ---------------- /* ----------------
@ -1406,6 +1409,8 @@ typedef struct PlanRowMark
* Then, since an Append-type node could have multiple partitioning * Then, since an Append-type node could have multiple partitioning
* hierarchies among its children, we have an unordered List of those Lists. * hierarchies among its children, we have an unordered List of those Lists.
* *
* root_parent_relids RelOptInfo.relids of the relation to which the parent
* plan node and this PartitionPruneInfo node belong
* prune_infos List of Lists containing PartitionedRelPruneInfo nodes, * prune_infos List of Lists containing PartitionedRelPruneInfo nodes,
* one sublist per run-time-prunable partition hierarchy * one sublist per run-time-prunable partition hierarchy
* appearing in the parent plan node's subplans. * appearing in the parent plan node's subplans.
@ -1418,6 +1423,7 @@ typedef struct PartitionPruneInfo
pg_node_attr(no_equal) pg_node_attr(no_equal)
NodeTag type; NodeTag type;
Bitmapset *root_parent_relids;
List *prune_infos; List *prune_infos;
Bitmapset *other_subplans; Bitmapset *other_subplans;
} PartitionPruneInfo; } PartitionPruneInfo;

View File

@ -70,7 +70,7 @@ typedef struct PartitionPruneContext
#define PruneCxtStateIdx(partnatts, step_id, keyno) \ #define PruneCxtStateIdx(partnatts, step_id, keyno) \
((partnatts) * (step_id) + (keyno)) ((partnatts) * (step_id) + (keyno))
extern PartitionPruneInfo *make_partition_pruneinfo(struct PlannerInfo *root, extern int make_partition_pruneinfo(struct PlannerInfo *root,
struct RelOptInfo *parentrel, struct RelOptInfo *parentrel,
List *subpaths, List *subpaths,
List *prunequal); List *prunequal);