From b350a734bccf679d033a6238dbafd1b834723ff3 Mon Sep 17 00:00:00 2001 From: "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