v37-0004-Fix-inheritance_planner-to-avoid-useless-work.patch

text/plain

Filename: v37-0004-Fix-inheritance_planner-to-avoid-useless-work.patch
Type: text/plain
Part: 3
Message: Re: speeding up planning with partitions

Patch

Format: format-patch
Series: patch v37-0004
Subject: Fix inheritance_planner to avoid useless work
File+
src/backend/optimizer/plan/planner.c 28 33
From cfd71ab1d1971f6ae1d7040b8ffcfbd1f10960cc Mon Sep 17 00:00:00 2001
From: amit <amitlangote09@gmail.com>
Date: Mon, 25 Mar 2019 17:14:02 +0900
Subject: [PATCH v37 4/5] Fix 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 | 61 +++++++++++++++++-------------------
 1 file changed, 28 insertions(+), 33 deletions(-)

diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index dbb9531d6c..92f506fef9 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -1188,7 +1188,6 @@ inheritance_planner(PlannerInfo *root)
 	Query	   *parse = root->parse;
 	int			top_parentRTindex = parse->resultRelation;
 	Bitmapset  *subqueryRTindexes;
-	Bitmapset  *modifiableARIindexes;
 	int			nominalRelation = -1;
 	Index		rootRelation = 0;
 	List	   *final_rtable = NIL;
@@ -1209,6 +1208,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);
 
 	Assert(parse->commandType != CMD_INSERT);
@@ -1253,10 +1253,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);
 
@@ -1266,32 +1268,6 @@ inheritance_planner(PlannerInfo *root)
 	}
 
 	/*
-	 * Next, we want to identify which AppendRelInfo items contain references
-	 * to any of the aforesaid subquery RTEs.  These items will need to be
-	 * copied and modified to adjust their subquery references; whereas the
-	 * other ones need not be touched.  It's worth being tense over this
-	 * because we can usually avoid processing most of the AppendRelInfo
-	 * items, thereby saving O(N^2) space and time when the target is a large
-	 * inheritance tree.  We can identify AppendRelInfo items by their
-	 * child_relid, since that should be unique within the list.
-	 */
-	modifiableARIindexes = NULL;
-	if (subqueryRTindexes != NULL)
-	{
-		foreach(lc, root->append_rel_list)
-		{
-			AppendRelInfo *appinfo = lfirst_node(AppendRelInfo, lc);
-
-			if (bms_is_member(appinfo->parent_relid, subqueryRTindexes) ||
-				bms_is_member(appinfo->child_relid, subqueryRTindexes) ||
-				bms_overlap(pull_varnos((Node *) appinfo->translated_vars),
-							subqueryRTindexes))
-				modifiableARIindexes = bms_add_member(modifiableARIindexes,
-													  appinfo->child_relid);
-		}
-	}
-
-	/*
 	 * If the parent RTE is a partitioned table, we should use that as the
 	 * nominal target relation, because the RTEs added for partitioned tables
 	 * (including the root parent) as child members of the inheritance set do
@@ -1327,6 +1303,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))
@@ -1362,11 +1339,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
@@ -1451,17 +1447,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