mirror of
https://github.com/postgres/postgres.git
synced 2025-05-22 00:02:02 -04:00
Track a Bitmapset of non-pruned partitions in RelOptInfo
For partitioned tables with large numbers of partitions where queries are able to prune all but a very small number of partitions, the time spent in the planner looping over RelOptInfo.part_rels checking for non-NULL RelOptInfos could become a large portion of the overall planning time. Here we add a Bitmapset that records the non-pruned partitions. This allows us to more efficiently skip the pruned partitions by looping over the Bitmapset. This will cause a very slight slow down in cases where no or not many partitions could be pruned, however, those cases are already slow to plan anyway and the overhead of looping over the Bitmapset would be unmeasurable when compared with the other tasks such as path creation for a large number of partitions. Reviewed-by: Amit Langote, Zhihong Yu Discussion: https://postgr.es/m/CAApHDvqnPx6JnUuPwaf5ao38zczrAb9mxt9gj4U1EKFfd4AqLA@mail.gmail.com
This commit is contained in:
parent
a5cb4f9829
commit
475dbd0b71
@ -2386,6 +2386,7 @@ _outRelOptInfo(StringInfo str, const RelOptInfo *node)
|
|||||||
WRITE_BOOL_FIELD(consider_partitionwise_join);
|
WRITE_BOOL_FIELD(consider_partitionwise_join);
|
||||||
WRITE_BITMAPSET_FIELD(top_parent_relids);
|
WRITE_BITMAPSET_FIELD(top_parent_relids);
|
||||||
WRITE_BOOL_FIELD(partbounds_merged);
|
WRITE_BOOL_FIELD(partbounds_merged);
|
||||||
|
WRITE_BITMAPSET_FIELD(live_parts);
|
||||||
WRITE_BITMAPSET_FIELD(all_partrels);
|
WRITE_BITMAPSET_FIELD(all_partrels);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1539,6 +1539,7 @@ try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
|
|||||||
child_sjinfo,
|
child_sjinfo,
|
||||||
child_sjinfo->jointype);
|
child_sjinfo->jointype);
|
||||||
joinrel->part_rels[cnt_parts] = child_joinrel;
|
joinrel->part_rels[cnt_parts] = child_joinrel;
|
||||||
|
joinrel->live_parts = bms_add_member(joinrel->live_parts, cnt_parts);
|
||||||
joinrel->all_partrels = bms_add_members(joinrel->all_partrels,
|
joinrel->all_partrels = bms_add_members(joinrel->all_partrels,
|
||||||
child_joinrel->relids);
|
child_joinrel->relids);
|
||||||
}
|
}
|
||||||
|
@ -6989,19 +6989,22 @@ apply_scanjoin_target_to_paths(PlannerInfo *root,
|
|||||||
if (rel_is_partitioned)
|
if (rel_is_partitioned)
|
||||||
{
|
{
|
||||||
List *live_children = NIL;
|
List *live_children = NIL;
|
||||||
int partition_idx;
|
int i;
|
||||||
|
|
||||||
/* Adjust each partition. */
|
/* Adjust each partition. */
|
||||||
for (partition_idx = 0; partition_idx < rel->nparts; partition_idx++)
|
i = -1;
|
||||||
|
while ((i = bms_next_member(rel->live_parts, i)) >= 0)
|
||||||
{
|
{
|
||||||
RelOptInfo *child_rel = rel->part_rels[partition_idx];
|
RelOptInfo *child_rel = rel->part_rels[i];
|
||||||
AppendRelInfo **appinfos;
|
AppendRelInfo **appinfos;
|
||||||
int nappinfos;
|
int nappinfos;
|
||||||
List *child_scanjoin_targets = NIL;
|
List *child_scanjoin_targets = NIL;
|
||||||
ListCell *lc;
|
ListCell *lc;
|
||||||
|
|
||||||
/* Pruned or dummy children can be ignored. */
|
Assert(child_rel != NULL);
|
||||||
if (child_rel == NULL || IS_DUMMY_REL(child_rel))
|
|
||||||
|
/* Dummy children can be ignored. */
|
||||||
|
if (IS_DUMMY_REL(child_rel))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Translate scan/join targets for this child. */
|
/* Translate scan/join targets for this child. */
|
||||||
@ -7082,32 +7085,36 @@ create_partitionwise_grouping_paths(PlannerInfo *root,
|
|||||||
PartitionwiseAggregateType patype,
|
PartitionwiseAggregateType patype,
|
||||||
GroupPathExtraData *extra)
|
GroupPathExtraData *extra)
|
||||||
{
|
{
|
||||||
int nparts = input_rel->nparts;
|
|
||||||
int cnt_parts;
|
|
||||||
List *grouped_live_children = NIL;
|
List *grouped_live_children = NIL;
|
||||||
List *partially_grouped_live_children = NIL;
|
List *partially_grouped_live_children = NIL;
|
||||||
PathTarget *target = grouped_rel->reltarget;
|
PathTarget *target = grouped_rel->reltarget;
|
||||||
bool partial_grouping_valid = true;
|
bool partial_grouping_valid = true;
|
||||||
|
int i;
|
||||||
|
|
||||||
Assert(patype != PARTITIONWISE_AGGREGATE_NONE);
|
Assert(patype != PARTITIONWISE_AGGREGATE_NONE);
|
||||||
Assert(patype != PARTITIONWISE_AGGREGATE_PARTIAL ||
|
Assert(patype != PARTITIONWISE_AGGREGATE_PARTIAL ||
|
||||||
partially_grouped_rel != NULL);
|
partially_grouped_rel != NULL);
|
||||||
|
|
||||||
/* Add paths for partitionwise aggregation/grouping. */
|
/* Add paths for partitionwise aggregation/grouping. */
|
||||||
for (cnt_parts = 0; cnt_parts < nparts; cnt_parts++)
|
i = -1;
|
||||||
|
while ((i = bms_next_member(input_rel->live_parts, i)) >= 0)
|
||||||
{
|
{
|
||||||
RelOptInfo *child_input_rel = input_rel->part_rels[cnt_parts];
|
RelOptInfo *child_input_rel = input_rel->part_rels[i];
|
||||||
PathTarget *child_target = copy_pathtarget(target);
|
PathTarget *child_target;
|
||||||
AppendRelInfo **appinfos;
|
AppendRelInfo **appinfos;
|
||||||
int nappinfos;
|
int nappinfos;
|
||||||
GroupPathExtraData child_extra;
|
GroupPathExtraData child_extra;
|
||||||
RelOptInfo *child_grouped_rel;
|
RelOptInfo *child_grouped_rel;
|
||||||
RelOptInfo *child_partially_grouped_rel;
|
RelOptInfo *child_partially_grouped_rel;
|
||||||
|
|
||||||
/* Pruned or dummy children can be ignored. */
|
Assert(child_input_rel != NULL);
|
||||||
if (child_input_rel == NULL || IS_DUMMY_REL(child_input_rel))
|
|
||||||
|
/* Dummy children can be ignored. */
|
||||||
|
if (IS_DUMMY_REL(child_input_rel))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
child_target = copy_pathtarget(target);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy the given "extra" structure as is and then override the
|
* Copy the given "extra" structure as is and then override the
|
||||||
* members specific to this child.
|
* members specific to this child.
|
||||||
|
@ -348,7 +348,7 @@ expand_partitioned_rtentry(PlannerInfo *root, RelOptInfo *relinfo,
|
|||||||
* that survive pruning. Below, we will initialize child objects for the
|
* that survive pruning. Below, we will initialize child objects for the
|
||||||
* surviving partitions.
|
* surviving partitions.
|
||||||
*/
|
*/
|
||||||
live_parts = prune_append_rel_partitions(relinfo);
|
relinfo->live_parts = live_parts = prune_append_rel_partitions(relinfo);
|
||||||
|
|
||||||
/* Expand simple_rel_array and friends to hold child objects. */
|
/* Expand simple_rel_array and friends to hold child objects. */
|
||||||
num_live_parts = bms_num_members(live_parts);
|
num_live_parts = bms_num_members(live_parts);
|
||||||
|
@ -255,6 +255,7 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
|
|||||||
rel->partbounds_merged = false;
|
rel->partbounds_merged = false;
|
||||||
rel->partition_qual = NIL;
|
rel->partition_qual = NIL;
|
||||||
rel->part_rels = NULL;
|
rel->part_rels = NULL;
|
||||||
|
rel->live_parts = NULL;
|
||||||
rel->all_partrels = NULL;
|
rel->all_partrels = NULL;
|
||||||
rel->partexprs = NULL;
|
rel->partexprs = NULL;
|
||||||
rel->nullable_partexprs = NULL;
|
rel->nullable_partexprs = NULL;
|
||||||
@ -669,6 +670,7 @@ build_join_rel(PlannerInfo *root,
|
|||||||
joinrel->partbounds_merged = false;
|
joinrel->partbounds_merged = false;
|
||||||
joinrel->partition_qual = NIL;
|
joinrel->partition_qual = NIL;
|
||||||
joinrel->part_rels = NULL;
|
joinrel->part_rels = NULL;
|
||||||
|
joinrel->live_parts = NULL;
|
||||||
joinrel->all_partrels = NULL;
|
joinrel->all_partrels = NULL;
|
||||||
joinrel->partexprs = NULL;
|
joinrel->partexprs = NULL;
|
||||||
joinrel->nullable_partexprs = NULL;
|
joinrel->nullable_partexprs = NULL;
|
||||||
@ -847,6 +849,7 @@ build_child_join_rel(PlannerInfo *root, RelOptInfo *outer_rel,
|
|||||||
joinrel->partbounds_merged = false;
|
joinrel->partbounds_merged = false;
|
||||||
joinrel->partition_qual = NIL;
|
joinrel->partition_qual = NIL;
|
||||||
joinrel->part_rels = NULL;
|
joinrel->part_rels = NULL;
|
||||||
|
joinrel->live_parts = NULL;
|
||||||
joinrel->all_partrels = NULL;
|
joinrel->all_partrels = NULL;
|
||||||
joinrel->partexprs = NULL;
|
joinrel->partexprs = NULL;
|
||||||
joinrel->nullable_partexprs = NULL;
|
joinrel->nullable_partexprs = NULL;
|
||||||
|
@ -654,15 +654,14 @@ make_partitionedrel_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel,
|
|||||||
relid_map = (Oid *) palloc0(nparts * sizeof(Oid));
|
relid_map = (Oid *) palloc0(nparts * sizeof(Oid));
|
||||||
present_parts = NULL;
|
present_parts = NULL;
|
||||||
|
|
||||||
for (i = 0; i < nparts; i++)
|
i = -1;
|
||||||
|
while ((i = bms_next_member(subpart->live_parts, i)) >= 0)
|
||||||
{
|
{
|
||||||
RelOptInfo *partrel = subpart->part_rels[i];
|
RelOptInfo *partrel = subpart->part_rels[i];
|
||||||
int subplanidx;
|
int subplanidx;
|
||||||
int subpartidx;
|
int subpartidx;
|
||||||
|
|
||||||
/* Skip processing pruned partitions. */
|
Assert(partrel != NULL);
|
||||||
if (partrel == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
subplan_map[i] = subplanidx = relid_subplan_map[partrel->relid] - 1;
|
subplan_map[i] = subplanidx = relid_subplan_map[partrel->relid] - 1;
|
||||||
subpart_map[i] = subpartidx = relid_subpart_map[partrel->relid] - 1;
|
subpart_map[i] = subpartidx = relid_subpart_map[partrel->relid] - 1;
|
||||||
|
@ -762,6 +762,9 @@ typedef struct RelOptInfo
|
|||||||
List *partition_qual; /* Partition constraint, if not the root */
|
List *partition_qual; /* Partition constraint, if not the root */
|
||||||
struct RelOptInfo **part_rels; /* Array of RelOptInfos of partitions,
|
struct RelOptInfo **part_rels; /* Array of RelOptInfos of partitions,
|
||||||
* stored in the same order as bounds */
|
* stored in the same order as bounds */
|
||||||
|
Bitmapset *live_parts; /* Bitmap with members acting as indexes into
|
||||||
|
* the part_rels[] array to indicate which
|
||||||
|
* partitions survived partition pruning. */
|
||||||
Relids all_partrels; /* Relids set of all partition relids */
|
Relids all_partrels; /* Relids set of all partition relids */
|
||||||
List **partexprs; /* Non-nullable partition key expressions */
|
List **partexprs; /* Non-nullable partition key expressions */
|
||||||
List **nullable_partexprs; /* Nullable partition key expressions */
|
List **nullable_partexprs; /* Nullable partition key expressions */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user