Commit 321f648a authored by Tom Lane's avatar Tom Lane

Assorted cosmetic cleanup of run-time-partition-pruning code.

Use "subplan" rather than "subnode" to refer to the child plans of
a partitioning Append; this seems a bit more specific and hence
clearer.  Improve assorted comments.  No non-cosmetic changes.

David Rowley and Tom Lane

Discussion: https://postgr.es/m/CAFj8pRBjrufA3ocDm8o4LPGNye9Y+pm1b9kCwode4X04CULG3g@mail.gmail.com
parent 939449de
This diff is collapsed.
......@@ -1186,7 +1186,7 @@ _copyPartitionPruneInfo(const PartitionPruneInfo *from)
COPY_BITMAPSET_FIELD(present_parts);
COPY_SCALAR_FIELD(nparts);
COPY_SCALAR_FIELD(nexprs);
COPY_POINTER_FIELD(subnode_map, from->nparts * sizeof(int));
COPY_POINTER_FIELD(subplan_map, from->nparts * sizeof(int));
COPY_POINTER_FIELD(subpart_map, from->nparts * sizeof(int));
COPY_POINTER_FIELD(hasexecparam, from->nexprs * sizeof(bool));
COPY_SCALAR_FIELD(do_initial_prune);
......
......@@ -1023,9 +1023,9 @@ _outPartitionPruneInfo(StringInfo str, const PartitionPruneInfo *node)
WRITE_INT_FIELD(nparts);
WRITE_INT_FIELD(nexprs);
appendStringInfoString(str, " :subnode_map");
appendStringInfoString(str, " :subplan_map");
for (i = 0; i < node->nparts; i++)
appendStringInfo(str, " %d", node->subnode_map[i]);
appendStringInfo(str, " %d", node->subplan_map[i]);
appendStringInfoString(str, " :subpart_map");
for (i = 0; i < node->nparts; i++)
......
......@@ -2333,7 +2333,7 @@ _readPartitionPruneInfo(void)
READ_BITMAPSET_FIELD(present_parts);
READ_INT_FIELD(nparts);
READ_INT_FIELD(nexprs);
READ_INT_ARRAY(subnode_map, local_node->nparts);
READ_INT_ARRAY(subplan_map, local_node->nparts);
READ_INT_ARRAY(subpart_map, local_node->nparts);
READ_BOOL_ARRAY(hasexecparam, local_node->nexprs);
READ_BOOL_FIELD(do_initial_prune);
......
......@@ -4,28 +4,24 @@
* Support for partition pruning during query planning and execution
*
* This module implements partition pruning using the information contained in
* table's partition descriptor, query clauses, and run-time parameters.
* a table's partition descriptor, query clauses, and run-time parameters.
*
* During planning, clauses that can be matched to the table's partition key
* are turned into a set of "pruning steps", which are then executed to
* produce a set of partitions (as indexes of the RelOptInfo->part_rels array)
* that satisfy the constraints in the step. Partitions not in the set are said
* to have been pruned.
* identify a set of partitions (as indexes in the RelOptInfo->part_rels
* array) that satisfy the constraints in the step. Partitions not in the set
* are said to have been pruned.
*
* A base pruning step may also consist of expressions whose values are only
* known during execution, such as Params, in which case pruning cannot occur
* A base pruning step may involve expressions whose values are only known
* during execution, such as Params, in which case pruning cannot occur
* entirely during planning. In that case, such steps are included alongside
* the plan, so that they can be used by the executor for further pruning.
*
* There are two kinds of pruning steps: a "base" pruning step, which contains
* information extracted from one or more clauses that are matched to the
* (possibly multi-column) partition key, such as the expressions whose values
* to match against partition bounds and operator strategy to associate to
* each expression. The other kind is a "combine" pruning step, which combines
* the outputs of some other steps using the appropriate combination method.
* All steps that are constructed are executed in succession such that for any
* "combine" step, all of the steps whose output it depends on are executed
* first and their ouput preserved.
* There are two kinds of pruning steps. A "base" pruning step represents
* tests on partition key column(s), typically comparisons to expressions.
* A "combine" pruning step represents a Boolean connector (AND/OR), and
* combines the outputs of some previous steps using the appropriate
* combination method.
*
* See gen_partprune_steps_internal() for more details on step generation.
*
......@@ -65,19 +61,18 @@
*/
typedef struct PartClauseInfo
{
int keyno; /* Partition key number (0 to partnatts - 1) */
Oid opno; /* operator used to compare partkey to 'expr' */
int keyno; /* Partition key number (0 to partnatts - 1) */
Oid opno; /* operator used to compare partkey to expr */
bool op_is_ne; /* is clause's original operator <> ? */
Expr *expr; /* expr the partition key is compared to */
Oid cmpfn; /* Oid of function to compare 'expr' to the
* partition key */
int op_strategy; /* cached info. */
int op_strategy; /* btree strategy identifying the operator */
} PartClauseInfo;
/*
* PartClauseMatchStatus
* Describes the result match_clause_to_partition_key produces for a
* given clause and the partition key to match with that are passed to it
* Describes the result of match_clause_to_partition_key()
*/
typedef enum PartClauseMatchStatus
{
......@@ -177,6 +172,7 @@ static bool match_boolean_partition_clause(Oid partopfamily, Expr *clause,
static bool partkey_datum_from_expr(PartitionPruneContext *context,
Expr *expr, int stateidx, Datum *value);
/*
* make_partition_pruneinfo
* Build List of PartitionPruneInfos, one for each 'partitioned_rels'.
......@@ -196,18 +192,18 @@ make_partition_pruneinfo(PlannerInfo *root, List *partition_rels,
List *subpaths, List *prunequal)
{
RelOptInfo *targetpart = NULL;
ListCell *lc;
List *pinfolist = NIL;
int *relid_subnode_map;
bool doruntimeprune = false;
int *relid_subplan_map;
int *relid_subpart_map;
ListCell *lc;
int i;
bool doruntimeprune = false;
/*
* Allocate two arrays to store the 1-based indexes of the 'subpaths' and
* 'partitioned_rels' by relid.
*/
relid_subnode_map = palloc0(sizeof(int) * root->simple_rel_array_size);
relid_subplan_map = palloc0(sizeof(int) * root->simple_rel_array_size);
relid_subpart_map = palloc0(sizeof(int) * root->simple_rel_array_size);
i = 1;
......@@ -219,7 +215,7 @@ make_partition_pruneinfo(PlannerInfo *root, List *partition_rels,
Assert(IS_SIMPLE_REL(pathrel));
Assert(pathrel->relid < root->simple_rel_array_size);
relid_subnode_map[pathrel->relid] = i++;
relid_subplan_map[pathrel->relid] = i++;
}
/* Likewise for the partition_rels */
......@@ -243,7 +239,7 @@ make_partition_pruneinfo(PlannerInfo *root, List *partition_rels,
Bitmapset *present_parts;
int nparts = subpart->nparts;
int partnatts = subpart->part_scheme->partnatts;
int *subnode_map;
int *subplan_map;
int *subpart_map;
List *partprunequal;
List *pruning_steps;
......@@ -289,7 +285,7 @@ make_partition_pruneinfo(PlannerInfo *root, List *partition_rels,
return NIL;
}
subnode_map = (int *) palloc(nparts * sizeof(int));
subplan_map = (int *) palloc(nparts * sizeof(int));
subpart_map = (int *) palloc(nparts * sizeof(int));
present_parts = NULL;
......@@ -302,19 +298,18 @@ make_partition_pruneinfo(PlannerInfo *root, List *partition_rels,
for (i = 0; i < nparts; i++)
{
RelOptInfo *partrel = subpart->part_rels[i];
int subnodeidx = relid_subnode_map[partrel->relid] - 1;
int subplanidx = relid_subplan_map[partrel->relid] - 1;
int subpartidx = relid_subpart_map[partrel->relid] - 1;
subnode_map[i] = subnodeidx;
subplan_map[i] = subplanidx;
subpart_map[i] = subpartidx;
/*
* Record the indexes of all the partition indexes that we have
* subnodes or subparts for. This allows an optimization to skip
* attempting any run-time pruning when no Params are found
* matching the partition key at this level.
* subplans or subparts for. This allows an optimization to skip
* attempting any run-time pruning when it's irrelevant.
*/
if (subnodeidx >= 0 || subpartidx >= 0)
if (subplanidx >= 0 || subpartidx >= 0)
present_parts = bms_add_member(present_parts, i);
}
......@@ -325,16 +320,17 @@ make_partition_pruneinfo(PlannerInfo *root, List *partition_rels,
pinfo->pruning_steps = pruning_steps;
pinfo->present_parts = present_parts;
pinfo->nparts = nparts;
pinfo->subnode_map = subnode_map;
pinfo->subplan_map = subplan_map;
pinfo->subpart_map = subpart_map;
/* Determine which pruning types should be enabled at this level */
doruntimeprune |= analyze_partkey_exprs(pinfo, pruning_steps, partnatts);
doruntimeprune |= analyze_partkey_exprs(pinfo, pruning_steps,
partnatts);
pinfolist = lappend(pinfolist, pinfo);
}
pfree(relid_subnode_map);
pfree(relid_subplan_map);
pfree(relid_subpart_map);
if (doruntimeprune)
......
......@@ -114,21 +114,21 @@ typedef struct PartitionTupleRouting
/*-----------------------
* PartitionPruningData - Encapsulates all information required to support
* elimination of partitions in node types which support arbitrary Lists of
* subplans. Information stored here allows the planner's partition pruning
* functions to be called and the return value of partition indexes translated
* into the subpath indexes of node types such as Append, thus allowing us to
* bypass certain subnodes when we have proofs that indicate that no tuple
* matching the 'pruning_steps' will be found within.
* elimination of partitions in plan types which support arbitrary Lists of
* subplans. Information stored here allows the partition pruning functions
* to be called and the return value of partition indexes translated into the
* subpath indexes of plan types such as Append, thus allowing us to bypass a
* subplan when we can prove that no tuple matching the 'pruning_steps' will
* be found within.
*
* subnode_map An array containing the subnode index which
* subplan_map An array containing the subplan index which
* matches this partition index, or -1 if the
* subnode has been pruned already.
* subpart_map An array containing the offset into the
* 'partprunedata' array in PartitionPruning, or
* subplan has been pruned already.
* subpart_map An array containing the index into the
* partprunedata array in PartitionPruneState, or
* -1 if there is no such element in that array.
* present_parts A Bitmapset of the partition indexes that we
* have subnodes mapped for.
* have subplans mapped for.
* context Contains the context details required to call
* the partition pruning code.
* pruning_steps List of PartitionPruneSteps used to
......@@ -141,7 +141,7 @@ typedef struct PartitionTupleRouting
*/
typedef struct PartitionPruningData
{
int *subnode_map;
int *subplan_map;
int *subpart_map;
Bitmapset *present_parts;
PartitionPruneContext context;
......@@ -151,15 +151,15 @@ typedef struct PartitionPruningData
} PartitionPruningData;
/*-----------------------
* PartitionPruneState - State object required for executor nodes to perform
* partition pruning elimination of their subnodes. This encapsulates a
* PartitionPruneState - State object required for plan nodes to perform
* partition pruning elimination of their subplans. This encapsulates a
* flattened hierarchy of PartitionPruningData structs.
* This struct can be attached to node types which support arbitrary Lists of
* subnodes containing partitions to allow subnodes to be eliminated due to
* the clauses being unable to match to any tuple that the subnode could
* This struct can be attached to plan types which support arbitrary Lists of
* subplans containing partitions to allow subplans to be eliminated due to
* the clauses being unable to match to any tuple that the subplan could
* possibly produce.
*
* partprunedata Array of PartitionPruningData for the node's target
* partprunedata Array of PartitionPruningData for the plan's target
* partitioned relation. First element contains the
* details for the target partitioned table.
* num_partprunedata Number of items in 'partprunedata' array.
......@@ -167,10 +167,12 @@ typedef struct PartitionPruningData
* startup (at any hierarchy level).
* do_exec_prune true if pruning should be performed during
* executor run (at any hierarchy level).
* prune_context A memory context which can be used to call the query
* planner's partition prune functions.
* execparamids Contains paramids of PARAM_EXEC Params found within
* any of the partprunedata structs.
* any of the partprunedata structs. Pruning must be
* done again each time the value of one of these
* parameters changes.
* prune_context A short-lived memory context in which to execute the
* partition pruning functions.
*-----------------------
*/
typedef struct PartitionPruneState
......@@ -179,8 +181,8 @@ typedef struct PartitionPruneState
int num_partprunedata;
bool do_initial_prune;
bool do_exec_prune;
MemoryContext prune_context;
Bitmapset *execparamids;
MemoryContext prune_context;
} PartitionPruneState;
extern PartitionTupleRouting *ExecSetupPartitionTupleRouting(ModifyTableState *mtstate,
......@@ -211,6 +213,6 @@ extern PartitionPruneState *ExecSetupPartitionPruneState(PlanState *planstate,
List *partitionpruneinfo);
extern Bitmapset *ExecFindMatchingSubPlans(PartitionPruneState *prunestate);
extern Bitmapset *ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate,
int nsubnodes);
int nsubplans);
#endif /* EXECPARTITION_H */
......@@ -1055,19 +1055,21 @@ typedef struct PlanRowMark
* partitions.
*
* Here we store mapping details to allow translation of a partitioned table's
* index into subnode indexes for node types which support arbitrary numbers
* of sub nodes, such as Append.
* index as returned by the partition pruning code into subplan indexes for
* plan types which support arbitrary numbers of subplans, such as Append.
* We also store various details to tell the executor when it should be
* performing partition pruning.
*/
typedef struct PartitionPruneInfo
{
NodeTag type;
Oid reloid; /* Oid of partition rel */
List *pruning_steps; /* List of PartitionPruneStep, see below */
Bitmapset *present_parts; /* Indexes of all partitions which subnodes
Bitmapset *present_parts; /* Indexes of all partitions which subplans
* are present for. */
int nparts; /* Length of subnode_map[] and subpart_map[] */
int nparts; /* Length of subplan_map[] and subpart_map[] */
int nexprs; /* Length of hasexecparam[] */
int *subnode_map; /* subnode index by partition id, or -1 */
int *subplan_map; /* subplan index by partition id, or -1 */
int *subpart_map; /* subpart index by partition id, or -1 */
bool *hasexecparam; /* true if corresponding pruning_step contains
* any PARAM_EXEC Params. */
......@@ -1099,9 +1101,9 @@ typedef struct PartitionPruneStep
* strategy of the operator in the clause matched to the last partition key.
* 'exprs' contains expressions which comprise the lookup key to be passed to
* the partition bound search function. 'cmpfns' contains the OIDs of
* comparison function used to compare aforementioned expressions with
* comparison functions used to compare aforementioned expressions with
* partition bounds. Both 'exprs' and 'cmpfns' contain the same number of
* items up to partnatts items.
* items, up to partnatts items.
*
* Once we find the offset of a partition bound using the lookup key, we
* determine which partitions to include in the result based on the value of
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment