self-join-removal.diff

text/x-patch

Filename: self-join-removal.diff
Type: text/x-patch
Part: 0
Message: Re: Removing unneeded self joins

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: unified
File+
src/backend/optimizer/plan/analyzejoins.c 44 54
diff --git a/src/backend/optimizer/plan/analyzejoins.c b/src/backend/optimizer/plan/analyzejoins.c
index d0d9b80be9c..d31427693da 100644
--- a/src/backend/optimizer/plan/analyzejoins.c
+++ b/src/backend/optimizer/plan/analyzejoins.c
@@ -1578,6 +1578,48 @@ restrict_infos_logically_equal(RestrictInfo *a, RestrictInfo *b)
 	return result;
 }
 
+/*
+ * The functions adds all non-redundant clauses to the keeping relation.
+ * Contradictory operation. On the one side, we reduce the length of
+ * restrict lists that can impact planning or executing time.
+ * Additionally, we improve the accuracy of cardinality estimation. On the
+ * other side, it is one more place that can make planning time much
+ * longer in specific cases. It would have been better to avoid calling
+ * the equal() function here, but it's the only way to detect duplicated
+ * inequality expressions.
+ */
+static void
+add_non_redundant_clauses(PlannerInfo *root,
+						  List *rinfo_candidates,
+						  List *keep_rinfo_list,
+						  Index removed_relid)
+{
+	foreach_node(RestrictInfo, rinfo, rinfo_candidates)
+	{
+		bool		is_redundant = false;
+
+		Assert(!bms_is_member(removed_relid, rinfo->required_relids));
+
+		foreach_node(RestrictInfo, src, keep_rinfo_list)
+		{
+			if (!bms_equal(src->clause_relids, rinfo->clause_relids))
+				/* Can't compare trivially different clauses */
+				continue;
+
+			if (src == rinfo ||
+				(rinfo->parent_ec != NULL &&
+				 src->parent_ec == rinfo->parent_ec) ||
+				 restrict_infos_logically_equal(rinfo, src))
+			{
+				is_redundant = true;
+				break;
+			}
+		}
+		if (!is_redundant)
+			distribute_restrictinfo_to_rels(root, rinfo);
+	}
+}
+
 /*
  * Remove a relation after we have proven that it participates only in an
  * unneeded unique self join.
@@ -1654,62 +1696,10 @@ remove_self_join_rel(PlannerInfo *root, PlanRowMark *kmark, PlanRowMark *rmark,
 
 	/*
 	 * Now, add all non-redundant clauses to the keeping relation.
-	 * Contradictory operation. On the one side, we reduce the length of
-	 * restrict lists that can impact planning or executing time.
-	 * Additionally, we improve the accuracy of cardinality estimation. On the
-	 * other side, it is one more place that can make planning time much
-	 * longer in specific cases. It would have been better to avoid calling
-	 * the equal() function here, but it's the only way to detect duplicated
-	 * inequality expressions.
 	 */
-	foreach_node(RestrictInfo, rinfo, binfo_candidates)
-	{
-		bool		is_redundant = false;
-
-		Assert(!bms_is_member(toRemove->relid, rinfo->required_relids));
-
-		foreach_node(RestrictInfo, src, toKeep->baserestrictinfo)
-		{
-			if (!bms_equal(src->clause_relids, rinfo->clause_relids))
-				/* Const and non-const expressions can't be equal */
-				continue;
-
-			if (src == rinfo ||
-				(rinfo->parent_ec != NULL
-				 && src->parent_ec == rinfo->parent_ec)
-				|| restrict_infos_logically_equal(rinfo, src))
-			{
-				is_redundant = true;
-				break;
-			}
-		}
-		if (!is_redundant)
-			distribute_restrictinfo_to_rels(root, rinfo);
-	}
-	foreach_node(RestrictInfo, rinfo, jinfo_candidates)
-	{
-		bool		is_redundant = false;
-
-		Assert(!bms_is_member(toRemove->relid, rinfo->required_relids));
+	add_non_redundant_clauses(root, binfo_candidates, toKeep->baserestrictinfo, toRemove->relid);
+	add_non_redundant_clauses(root, jinfo_candidates, toKeep->joininfo, toRemove->relid);
 
-		foreach_node(RestrictInfo, src, toKeep->joininfo)
-		{
-			if (!bms_equal(src->clause_relids, rinfo->clause_relids))
-				/* Can't compare trivially different clauses */
-				continue;
-
-			if (src == rinfo ||
-				(rinfo->parent_ec != NULL
-				 && src->parent_ec == rinfo->parent_ec)
-				|| restrict_infos_logically_equal(rinfo, src))
-			{
-				is_redundant = true;
-				break;
-			}
-		}
-		if (!is_redundant)
-			distribute_restrictinfo_to_rels(root, rinfo);
-	}
 	list_free(binfo_candidates);
 	list_free(jinfo_candidates);