diff options
| author | Amit Langote | 2025-02-07 08:15:09 +0000 |
|---|---|---|
| committer | Amit Langote | 2025-02-07 08:15:09 +0000 |
| commit | cbc127917e04a978a788b8bc9d35a70244396d5b (patch) | |
| tree | 9a3325897700ed0a8a57b3ef284b4ce778d1b4ff /src/include/nodes | |
| parent | 926c7fce03603b49dd2529e37d47b805730584fc (diff) | |
Track unpruned relids to avoid processing pruned relations
This commit introduces changes to track unpruned relations explicitly,
making it possible for top-level plan nodes, such as ModifyTable and
LockRows, to avoid processing partitions pruned during initial
pruning. Scan-level nodes, such as Append and MergeAppend, already
avoid the unnecessary processing by accessing partition pruning
results directly via part_prune_index. In contrast, top-level nodes
cannot access pruning results directly and need to determine which
partitions remain unpruned.
To address this, this commit introduces a new bitmapset field,
es_unpruned_relids, which the executor uses to track the set of
unpruned relations. This field is referenced during plan
initialization to skip initializing certain nodes for pruned
partitions. It is initialized with PlannedStmt.unprunableRelids,
a new field that the planner populates with RT indexes of relations
that cannot be pruned during runtime pruning. These include relations
not subject to partition pruning and those required for execution
regardless of pruning.
PlannedStmt.unprunableRelids is computed during set_plan_refs() by
removing the RT indexes of runtime-prunable relations, identified
from PartitionPruneInfos, from the full set of relation RT indexes.
ExecDoInitialPruning() then updates es_unpruned_relids by adding
partitions that survive initial pruning.
To support this, PartitionedRelPruneInfo and PartitionedRelPruningData
now include a leafpart_rti_map[] array that maps partition indexes to
their corresponding RT indexes. The former is used in set_plan_refs()
when constructing unprunableRelids, while the latter is used in
ExecDoInitialPruning() to convert partition indexes returned by
get_matching_partitions() into RT indexes, which are then added to
es_unpruned_relids.
These changes make it possible for ModifyTable and LockRows nodes to
process only relations that remain unpruned after initial pruning.
ExecInitModifyTable() trims lists, such as resultRelations,
withCheckOptionLists, returningLists, and updateColnosLists, to
consider only unpruned partitions. It also creates ResultRelInfo
structs only for these partitions. Similarly, child RowMarks for
pruned relations are skipped.
By avoiding unnecessary initialization of structures for pruned
partitions, these changes improve the performance of updates and
deletes on partitioned tables during initial runtime pruning.
Due to ExecInitModifyTable() changes as described above, EXPLAIN on a
plan for UPDATE and DELETE that uses runtime initial pruning no longer
lists partitions pruned during initial pruning.
Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier versions)
Reviewed-by: Tomas Vondra <tomas@vondra.me>
Discussion: https://postgr.es/m/CA+HiwqFGkMSge6TgC9KQzde0ohpAycLQuV7ooitEEpbKB0O_mg@mail.gmail.com
Diffstat (limited to 'src/include/nodes')
| -rw-r--r-- | src/include/nodes/execnodes.h | 10 | ||||
| -rw-r--r-- | src/include/nodes/pathnodes.h | 13 | ||||
| -rw-r--r-- | src/include/nodes/plannodes.h | 35 |
3 files changed, 46 insertions, 12 deletions
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index aca15f771a2..a2cba97e3d5 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -658,6 +658,10 @@ typedef struct EState List *es_part_prune_infos; /* List of PartitionPruneInfo */ List *es_part_prune_states; /* List of PartitionPruneState */ List *es_part_prune_results; /* List of Bitmapset */ + Bitmapset *es_unpruned_relids; /* PlannedStmt.unprunableRelids + RT + * indexes of leaf partitions that survive + * initial pruning; see + * ExecDoInitialPruning() */ const char *es_sourceText; /* Source text from QueryDesc */ JunkFilter *es_junkFilter; /* top-level junk filter, if any */ @@ -1440,6 +1444,12 @@ typedef struct ModifyTableState double mt_merge_inserted; double mt_merge_updated; double mt_merge_deleted; + + /* + * List of valid updateColnosLists. Contains only those belonging to + * unpruned relations from ModifyTable.updateColnosLists. + */ + List *mt_updateColnosLists; } ModifyTableState; /* ---------------- diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 52d44f43021..00c700cc3e7 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -116,6 +116,19 @@ typedef struct PlannerGlobal /* "flat" rangetable for executor */ List *finalrtable; + /* + * RT indexes of all relation RTEs in finalrtable (RTE_RELATION and + * RTE_SUBQUERY RTEs of views) + */ + Bitmapset *allRelids; + + /* + * RT indexes of all leaf partitions in nodes that support pruning and are + * subject to runtime pruning at plan initialization time ("initial" + * pruning). + */ + Bitmapset *prunableRelids; + /* "flat" list of RTEPermissionInfos */ List *finalrteperminfos; diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index 06d9559ebb9..2a2cf816cb6 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -74,6 +74,10 @@ typedef struct PlannedStmt List *rtable; /* list of RangeTblEntry nodes */ + Bitmapset *unprunableRelids; /* RT indexes of relations that are not + * subject to runtime pruning or are + * needed to perform runtime pruning */ + List *permInfos; /* list of RTEPermissionInfo nodes for rtable * entries needing one */ @@ -1449,18 +1453,22 @@ typedef struct PartitionPruneInfo * PartitionedRelPruneInfo - Details required to allow the executor to prune * partitions for a single partitioned table. * - * subplan_map[] and subpart_map[] are indexed by partition index of the - * partitioned table referenced by 'rtindex', the partition index being the - * order that the partitions are defined in the table's PartitionDesc. For a - * leaf partition p, subplan_map[p] contains the zero-based index of the - * partition's subplan in the parent plan's subplan list; it is -1 if the - * partition is non-leaf or has been pruned. For a non-leaf partition p, - * subpart_map[p] contains the zero-based index of that sub-partition's - * PartitionedRelPruneInfo in the hierarchy's PartitionedRelPruneInfo list; - * it is -1 if the partition is a leaf or has been pruned. Note that subplan - * indexes, as stored in 'subplan_map', are global across the parent plan - * node, but partition indexes are valid only within a particular hierarchy. - * relid_map[p] contains the partition's OID, or 0 if the partition was pruned. + * subplan_map[], subpart_map[], and leafpart_rti_map[] are indexed by partition + * index of the partitioned table referenced by 'rtindex', the partition index + * being the order that the partitions are defined in the table's + * PartitionDesc. For a leaf partition p, subplan_map[p] contains the + * zero-based index of the partition's subplan in the parent plan's subplan + * list; it is -1 if the partition is non-leaf or has been pruned. For a + * non-leaf partition p, subpart_map[p] contains the zero-based index of that + * sub-partition's PartitionedRelPruneInfo in the hierarchy's + * PartitionedRelPruneInfo list; it is -1 if the partition is a leaf or has + * been pruned. leafpart_rti_map[p] contains the RT index of a leaf partition + * if its subplan is in the parent plan' subplan list; it is 0 either if the + * partition is non-leaf or it is leaf but has been pruned during planning. + * Note that subplan indexes, as stored in 'subplan_map', are global across the + * parent plan node, but partition indexes are valid only within a particular + * hierarchy. relid_map[p] contains the partition's OID, or 0 if the partition + * was pruned. */ typedef struct PartitionedRelPruneInfo { @@ -1483,6 +1491,9 @@ typedef struct PartitionedRelPruneInfo /* subpart index by partition index, or -1 */ int *subpart_map pg_node_attr(array_size(nparts)); + /* RT index by partition index, or 0 */ + int *leafpart_rti_map pg_node_attr(array_size(nparts)); + /* relation OID by partition index, or 0 */ Oid *relid_map pg_node_attr(array_size(nparts)); |
