From 31e7240faaf1facc1c179970fd776f27268de345 Mon Sep 17 00:00:00 2001 From: amit Date: Fri, 8 Mar 2019 17:50:20 +0900 Subject: [PATCH v32 5/8] Further tweak inheritance_planner to avoid useless work When running adjust_appendrel_attrs() on the query, there's no need for its range table to contain child target RTEs, because they don't need to be translated. Trimming those off the range table makes range_table_mutator() finish much quicker, because now it doesn't have to crawl through potentially many RTEs essentially just copying them. Note that copying the child target RTEs is unnecessary as they won't be modified across different planning cycles. The (sub-) list they are contained still must copied with list_copy(), because more entries may be added to individual child query's range table. Furthermore, in a few places where the code iterates over the range table to first locate and later modify subquery RTEs, it's OK to ignore the child target RTEs, because there won't be any subquery RTEs among them and also they won't contain any references to subquery RTEs that are found. --- src/backend/optimizer/plan/planner.c | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 3851245dc7..123d07f2e2 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -1209,6 +1209,7 @@ inheritance_planner(PlannerInfo *root) Query *parent_parse; Bitmapset *parent_relids = bms_make_singleton(top_parentRTindex); PlannerInfo **parent_roots = NULL; + List *orig_rtable = list_copy(root->parse->rtable); List *orig_append_rel_list = list_copy(root->append_rel_list); List *source_appinfos = NIL; List *source_child_rowmarks = NIL; @@ -1257,10 +1258,12 @@ inheritance_planner(PlannerInfo *root) * management of the rowMarks list. * * To begin with, generate a bitmapset of the relids of the subquery RTEs. + * We use orig_rtable, not parse->rtable, because we wouldn't need to + * consider any newly added RTEs as they all must be RTE_RELATION entries. */ subqueryRTindexes = NULL; rti = 1; - foreach(lc, parse->rtable) + foreach(lc, orig_rtable) { RangeTblEntry *rte = lfirst_node(RangeTblEntry, lc); @@ -1306,6 +1309,7 @@ inheritance_planner(PlannerInfo *root) RangeTblEntry *child_rte; RelOptInfo *sub_final_rel; Path *subpath; + List *parent_rtable; /* append_rel_list contains all append rels; ignore others */ if (!bms_is_member(appinfo->parent_relid, parent_relids)) @@ -1332,11 +1336,30 @@ inheritance_planner(PlannerInfo *root) * adjust_appendrel_attrs, which copies the Query and changes * references to the parent RTE to refer to the current child RTE, * then fool around with subquery RTEs. + * + * In order to avoid range_table_mutator() uselessly spending time on + * the child target RTEs that were added to query at the beginning of + * this function, we swap the query's range table with the copy of the + * range table before they were added (orig_table). */ + parent_rtable = parent_parse->rtable; + parent_parse->rtable = orig_rtable; subroot->parse = (Query *) adjust_appendrel_attrs(parent_root, (Node *) parent_parse, 1, &appinfo); + /* + * We do however need to add those child target RTEs to the range + * table so that query_planner can find this child RTE. Other target + * RTEs will not be accessed during this planning cycle, but we can't + * just skip them. + */ + subroot->parse->rtable = + list_concat(subroot->parse->rtable, + list_copy_tail(parent_rtable, + list_length(orig_rtable))); + /* Put it back for the next child's planning. */ + parent_parse->rtable = parent_rtable; /* * If there are securityQuals attached to the parent, move them to the @@ -1465,17 +1488,16 @@ inheritance_planner(PlannerInfo *root) /* * If this isn't the first child Query, generate duplicates of all * subquery RTEs, and adjust Var numbering to reference the - * duplicates. To simplify the loop logic, we scan the original rtable - * not the copy just made by adjust_appendrel_attrs; that should be OK - * since subquery RTEs couldn't contain any references to the target - * rel. + * duplicates. Note that we scan the original rtable before any + * child target relations were added, which is OK, because no other + * RTEs would contain references to subquery rels being modified. */ if (final_rtable != NIL && subqueryRTindexes != NULL) { ListCell *lr; rti = 1; - foreach(lr, parent_parse->rtable) + foreach(lr, orig_rtable) { RangeTblEntry *rte = lfirst_node(RangeTblEntry, lr); -- 2.11.0