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);