0001-Allow-direct-lookups-of-AppendRelInfo-by-child-relid.patch
application/octet-stream
Filename: 0001-Allow-direct-lookups-of-AppendRelInfo-by-child-relid.patch
Type: application/octet-stream
Part: 0
Patch
Format: format-patch
Series: patch 0001
Subject: Allow direct lookups of AppendRelInfo by child relid
| File | + | − |
|---|---|---|
| src/backend/optimizer/plan/planner.c | 4 | 0 |
| src/backend/optimizer/prep/prepunion.c | 7 | 16 |
| src/backend/optimizer/util/relnode.c | 15 | 0 |
| src/include/nodes/relation.h | 4 | 0 |
From b350a734bccf679d033a6238dbafd1b834723ff3 Mon Sep 17 00:00:00 2001
From: "dgrowley@gmail.com" <dgrowley@gmail.com>
Date: Mon, 28 May 2018 14:24:09 +1200
Subject: [PATCH] Allow direct lookups of AppendRelInfo by child relid
find_appinfos_by_relids had quite a large overhead when the number of items in
the append_rel_list was high. Here we're just looking for a single
AppendRelInfo, so let's make an array so that can be looked up directly.
A test case with 10k RANGE partitions show that planning of an UPDATE to the
partitioned table is about twice as fast with this change.
---
src/backend/optimizer/plan/planner.c | 4 ++++
src/backend/optimizer/prep/prepunion.c | 23 +++++++----------------
src/backend/optimizer/util/relnode.c | 15 +++++++++++++++
src/include/nodes/relation.h | 4 ++++
4 files changed, 30 insertions(+), 16 deletions(-)
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 97adb270fc..db1890cdaa 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -1181,6 +1181,7 @@ inheritance_planner(PlannerInfo *root)
List *final_rtable = NIL;
int save_rel_array_size = 0;
RelOptInfo **save_rel_array = NULL;
+ AppendRelInfo **save_append_rel_array = NULL;
List *subpaths = NIL;
List *subroots = NIL;
List *resultRelations = NIL;
@@ -1590,6 +1591,7 @@ inheritance_planner(PlannerInfo *root)
}
save_rel_array_size = subroot->simple_rel_array_size;
save_rel_array = subroot->simple_rel_array;
+ save_append_rel_array = subroot->append_rel_array;
/* Make sure any initplans from this rel get into the outer list */
root->init_plans = subroot->init_plans;
@@ -1641,6 +1643,8 @@ inheritance_planner(PlannerInfo *root)
parse->rtable = final_rtable;
root->simple_rel_array_size = save_rel_array_size;
root->simple_rel_array = save_rel_array;
+ root->append_rel_array = save_append_rel_array;
+
/* Must reconstruct master's simple_rte_array, too */
root->simple_rte_array = (RangeTblEntry **)
palloc0((list_length(final_rtable) + 1) * sizeof(RangeTblEntry *));
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index eb9fe26cde..55853ed4c1 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -2703,29 +2703,20 @@ build_child_join_sjinfo(PlannerInfo *root, SpecialJoinInfo *parent_sjinfo,
AppendRelInfo **
find_appinfos_by_relids(PlannerInfo *root, Relids relids, int *nappinfos)
{
- ListCell *lc;
AppendRelInfo **appinfos;
int cnt = 0;
-
+ int i;
*nappinfos = bms_num_members(relids);
appinfos = (AppendRelInfo **) palloc(sizeof(AppendRelInfo *) * *nappinfos);
- foreach(lc, root->append_rel_list)
+ i = -1;
+ while ((i = bms_next_member(relids, i)) >= 0)
{
- AppendRelInfo *appinfo = lfirst(lc);
+ AppendRelInfo *appinfo = root->append_rel_array[i];
- if (bms_is_member(appinfo->child_relid, relids))
- {
- appinfos[cnt] = appinfo;
- cnt++;
+ Assert(appinfo);
- /* Stop when we have gathered all the AppendRelInfos. */
- if (cnt == *nappinfos)
- return appinfos;
- }
+ appinfos[cnt++] = appinfo;
}
-
- /* Should have found the entries ... */
- elog(ERROR, "did not find all requested child rels in append_rel_list");
- return NULL; /* not reached */
+ return appinfos;
}
diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
index 82b78420e7..7b4ea9f038 100644
--- a/src/backend/optimizer/util/relnode.c
+++ b/src/backend/optimizer/util/relnode.c
@@ -79,6 +79,10 @@ setup_simple_rel_arrays(PlannerInfo *root)
/* simple_rte_array is an array equivalent of the rtable list */
root->simple_rte_array = (RangeTblEntry **)
palloc0(root->simple_rel_array_size * sizeof(RangeTblEntry *));
+
+ root->append_rel_array = (AppendRelInfo **)
+ palloc0(root->simple_rel_array_size * sizeof(AppendRelInfo *));
+
rti = 1;
foreach(lc, root->parse->rtable)
{
@@ -86,6 +90,17 @@ setup_simple_rel_arrays(PlannerInfo *root)
root->simple_rte_array[rti++] = rte;
}
+
+ foreach(lc, root->append_rel_list)
+ {
+ AppendRelInfo *appinfo = lfirst_node(AppendRelInfo, lc);
+ int child_relid = appinfo->child_relid;
+
+ /* Sanity check */
+ Assert(child_relid < root->simple_rel_array_size);
+
+ root->append_rel_array[child_relid] = appinfo;
+ }
}
/*
diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h
index cd2ff27656..86730cc1bc 100644
--- a/src/include/nodes/relation.h
+++ b/src/include/nodes/relation.h
@@ -151,6 +151,7 @@ typedef struct PlannerGlobal
#define planner_subplan_get_plan(root, subplan) \
((Plan *) list_nth((root)->glob->subplans, (subplan)->plan_id - 1))
+struct AppendRelInfo;
/*----------
* PlannerInfo
@@ -201,6 +202,9 @@ typedef struct PlannerInfo
*/
RangeTblEntry **simple_rte_array; /* rangetable as an array */
+ struct AppendRelInfo **append_rel_array; /* append_rel_list indexed by
+ * child_relid */
+
/*
* all_baserels is a Relids set of all base relids (but not "other"
* relids) in the query; that is, the Relids identifier of the final join
--
2.16.2.windows.1