v28-0005-Teach-planner-to-only-process-unpruned-partition.patch
text/plain
Filename: v28-0005-Teach-planner-to-only-process-unpruned-partition.patch
Type: text/plain
Part: 4
Patch
Format: format-patch
Series: patch v28-0005
Subject: Teach planner to only process unpruned partitions
| File | + | − |
|---|---|---|
| src/backend/optimizer/path/joinrels.c | 3 | 0 |
| src/backend/optimizer/plan/planner.c | 9 | 9 |
| src/backend/optimizer/util/inherit.c | 6 | 0 |
| src/backend/optimizer/util/relnode.c | 4 | 0 |
| src/backend/partitioning/partprune.c | 6 | 13 |
| src/include/nodes/pathnodes.h | 4 | 0 |
From bf86b127ac5b122dc5b0849f61da7070a69d872a Mon Sep 17 00:00:00 2001
From: amit <amitlangote09@gmail.com>
Date: Mon, 4 Mar 2019 11:57:04 +0900
Subject: [PATCH v28 5/6] Teach planner to only process unpruned partitions
This adds a bitmapset field live_parts to RelOptInfo and stores
the partition indexes of non-dummy partitions in it, meaning it
contains indexes of only those partitions that have a non-NULL
RelOptInfo present in its parent's RelOptInfo's part_rels array.
This speeds up processing partitioned table's partitions compared
to going through the whole part_rels array in a number of places.
Partitionwise join still has to visit each member of part_rels,
because pruned children may fall on the nullable side of an outer
join and an empty Result path must be present for building the
outer join paths.
---
src/backend/optimizer/path/joinrels.c | 3 +++
src/backend/optimizer/plan/planner.c | 18 +++++++++---------
src/backend/optimizer/util/inherit.c | 6 ++++++
src/backend/optimizer/util/relnode.c | 4 ++++
src/backend/partitioning/partprune.c | 19 ++++++-------------
src/include/nodes/pathnodes.h | 4 ++++
6 files changed, 32 insertions(+), 22 deletions(-)
diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c
index 55a7a34061..a549c7669b 100644
--- a/src/backend/optimizer/path/joinrels.c
+++ b/src/backend/optimizer/path/joinrels.c
@@ -1497,6 +1497,9 @@ try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
populate_joinrel_with_paths(root, child_rel1, child_rel2,
child_joinrel, child_sjinfo,
child_restrictlist);
+ if (!IS_DUMMY_REL(child_joinrel))
+ joinrel->live_parts = bms_add_member(joinrel->live_parts,
+ cnt_parts);
}
if (baserel1)
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 82b7bbf59e..77f880c5ff 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -7080,7 +7080,9 @@ apply_scanjoin_target_to_paths(PlannerInfo *root,
int partition_idx;
/* Adjust each partition. */
- for (partition_idx = 0; partition_idx < rel->nparts; partition_idx++)
+ partition_idx = -1;
+ while ((partition_idx = bms_next_member(rel->live_parts,
+ partition_idx)) >= 0)
{
RelOptInfo *child_rel = rel->part_rels[partition_idx];
AppendRelInfo **appinfos;
@@ -7088,9 +7090,7 @@ apply_scanjoin_target_to_paths(PlannerInfo *root,
List *child_scanjoin_targets = NIL;
ListCell *lc;
- /* Skip processing pruned partitions. */
- if (child_rel == NULL)
- continue;
+ Assert(child_rel != NULL);
/* Translate scan/join targets for this child. */
appinfos = find_appinfos_by_relids(root, child_rel->relids,
@@ -7170,7 +7170,6 @@ create_partitionwise_grouping_paths(PlannerInfo *root,
PartitionwiseAggregateType patype,
GroupPathExtraData *extra)
{
- int nparts = input_rel->nparts;
int cnt_parts;
List *grouped_live_children = NIL;
List *partially_grouped_live_children = NIL;
@@ -7182,7 +7181,9 @@ create_partitionwise_grouping_paths(PlannerInfo *root,
partially_grouped_rel != NULL);
/* Add paths for partitionwise aggregation/grouping. */
- for (cnt_parts = 0; cnt_parts < nparts; cnt_parts++)
+ cnt_parts = -1;
+ while ((cnt_parts = bms_next_member(input_rel->live_parts,
+ cnt_parts)) >= 0)
{
RelOptInfo *child_input_rel = input_rel->part_rels[cnt_parts];
PathTarget *child_target = copy_pathtarget(target);
@@ -7192,9 +7193,8 @@ create_partitionwise_grouping_paths(PlannerInfo *root,
RelOptInfo *child_grouped_rel;
RelOptInfo *child_partially_grouped_rel;
- /* Skip processing pruned partitions. */
- if (child_input_rel == NULL)
- continue;
+ /* A live partition must have a RelOptInfo. */
+ Assert(child_input_rel != NULL);
/* Input child rel must have a path */
Assert(child_input_rel->pathlist != NIL);
diff --git a/src/backend/optimizer/util/inherit.c b/src/backend/optimizer/util/inherit.c
index 7c619cb44d..1fcccdae86 100644
--- a/src/backend/optimizer/util/inherit.c
+++ b/src/backend/optimizer/util/inherit.c
@@ -297,6 +297,12 @@ expand_partitioned_rtentry(PlannerInfo *root, RangeTblEntry *parentrte,
live_parts = prune_append_rel_partitions(rel);
/*
+ * Later steps that loop over part_rels should use these indexes
+ * to access unpruned partitions.
+ */
+ rel->live_parts = live_parts;
+
+ /*
* Expand simple_rel_array and friends to hold child objects.
*
* We'll need nparts + 1 new slots, because we also consider parent
diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
index 649f6c8481..dda12dca87 100644
--- a/src/backend/optimizer/util/relnode.c
+++ b/src/backend/optimizer/util/relnode.c
@@ -564,6 +564,7 @@ add_appendrel_other_rels(PlannerInfo *root, RangeTblEntry *rte, Index rti)
if (childrte->relid == partdesc->oids[i])
{
rel->part_rels[i] = childrel;
+ rel->live_parts = bms_add_member(rel->live_parts, i);
break;
}
}
@@ -1990,6 +1991,9 @@ build_joinrel_partition_info(RelOptInfo *joinrel, RelOptInfo *outer_rel,
joinrel->partexprs[cnt] = partexpr;
joinrel->nullable_partexprs[cnt] = nullable_partexpr;
}
+
+ /* Partitions will be added by try_partitionwise_join. */
+ joinrel->live_parts = NULL;
}
/*
diff --git a/src/backend/partitioning/partprune.c b/src/backend/partitioning/partprune.c
index 9ebded67a9..e766555a9f 100644
--- a/src/backend/partitioning/partprune.c
+++ b/src/backend/partitioning/partprune.c
@@ -440,30 +440,23 @@ make_partitionedrel_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel,
subpart_map = (int *) palloc(nparts * sizeof(int));
memset(subpart_map, -1, nparts * sizeof(int));
relid_map = (Oid *) palloc0(nparts * sizeof(int));
- present_parts = NULL;
+ present_parts = bms_copy(subpart->live_parts);
- for (i = 0; i < nparts; i++)
+ i = -1;
+ while ((i = bms_next_member(present_parts, i)) >= 0)
{
RelOptInfo *partrel = subpart->part_rels[i];
int subplanidx;
int subpartidx;
- /* Skip processing pruned partitions. */
- if (partrel == NULL)
- continue;
-
+ Assert(partrel != NULL);
subplan_map[i] = subplanidx = relid_subplan_map[partrel->relid] - 1;
subpart_map[i] = subpartidx = relid_subpart_map[partrel->relid] - 1;
relid_map[i] = planner_rt_fetch(partrel->relid, root)->relid;
- if (subplanidx >= 0)
- {
- present_parts = bms_add_member(present_parts, i);
- /* Record finding this subplan */
+ /* Record finding this subplan */
+ if (subplanidx >= 0)
subplansfound = bms_add_member(subplansfound, subplanidx);
- }
- else if (subpartidx >= 0)
- present_parts = bms_add_member(present_parts, i);
}
pinfo = makeNode(PartitionedRelPruneInfo);
diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h
index 31811f9adb..3298bd78ca 100644
--- a/src/include/nodes/pathnodes.h
+++ b/src/include/nodes/pathnodes.h
@@ -714,6 +714,10 @@ typedef struct RelOptInfo
List *partition_qual; /* partition constraint */
struct RelOptInfo **part_rels; /* Array of RelOptInfos of partitions,
* stored in the same order of bounds */
+ Bitmapset *live_parts; /* Indexes into part_rels of the non-NULL
+ * RelOptInfos of unpruned partitions; exists
+ * to avoid having to iterate over the entire
+ * part_rels array to filter NULL entries. */
List **partexprs; /* Non-nullable partition key expressions. */
List **nullable_partexprs; /* Nullable partition key expressions. */
List *partitioned_child_rels; /* List of RT indexes. */
--
2.11.0