From ec38dcd363cd63f2a1f3cc4c47680bb16e8331b4 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 20 Apr 2018 16:00:47 -0400 Subject: [PATCH] Tweak a couple of planner APIs to save recalculating join relids. Discussion: https://postgr.es/m/f8128b11-c5bf-3539-48cd-234178b2314d@proxel.se --- src/backend/optimizer/path/costsize.c | 6 +++--- src/backend/optimizer/path/joinpath.c | 4 +++- src/backend/optimizer/plan/analyzejoins.c | 12 ++++++++---- src/include/optimizer/cost.h | 1 + src/include/optimizer/planmain.h | 2 +- 5 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index 10d41141f2..957f751bd4 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -4023,6 +4023,7 @@ get_restriction_qual_cost(PlannerInfo *root, RelOptInfo *baserel, * them to all the join cost estimation functions. * * Input parameters: + * joinrel: join relation under consideration * outerrel: outer relation under consideration * innerrel: inner relation under consideration * jointype: if not JOIN_SEMI or JOIN_ANTI, we assume it's inner_unique @@ -4033,6 +4034,7 @@ get_restriction_qual_cost(PlannerInfo *root, RelOptInfo *baserel, */ void compute_semi_anti_join_factors(PlannerInfo *root, + RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, @@ -4056,14 +4058,12 @@ compute_semi_anti_join_factors(PlannerInfo *root, */ if (IS_OUTER_JOIN(jointype)) { - Relids joinrelids = bms_union(outerrel->relids, innerrel->relids); - joinquals = NIL; foreach(l, restrictlist) { RestrictInfo *rinfo = lfirst_node(RestrictInfo, l); - if (!RINFO_IS_PUSHED_DOWN(rinfo, joinrelids)) + if (!RINFO_IS_PUSHED_DOWN(rinfo, joinrel->relids)) joinquals = lappend(joinquals, rinfo); } } diff --git a/src/backend/optimizer/path/joinpath.c b/src/backend/optimizer/path/joinpath.c index f47dd8185b..450edfae46 100644 --- a/src/backend/optimizer/path/joinpath.c +++ b/src/backend/optimizer/path/joinpath.c @@ -171,6 +171,7 @@ add_paths_to_joinrel(PlannerInfo *root, break; case JOIN_UNIQUE_OUTER: extra.inner_unique = innerrel_is_unique(root, + joinrel->relids, outerrel->relids, innerrel, JOIN_INNER, @@ -179,6 +180,7 @@ add_paths_to_joinrel(PlannerInfo *root, break; default: extra.inner_unique = innerrel_is_unique(root, + joinrel->relids, outerrel->relids, innerrel, jointype, @@ -207,7 +209,7 @@ add_paths_to_joinrel(PlannerInfo *root, * for cost estimation. These will be the same for all paths. */ if (jointype == JOIN_SEMI || jointype == JOIN_ANTI || extra.inner_unique) - compute_semi_anti_join_factors(root, outerrel, innerrel, + compute_semi_anti_join_factors(root, joinrel, outerrel, innerrel, jointype, sjinfo, restrictlist, &extra.semifactors); diff --git a/src/backend/optimizer/plan/analyzejoins.c b/src/backend/optimizer/plan/analyzejoins.c index c5c4362609..0e73f9cf4c 100644 --- a/src/backend/optimizer/plan/analyzejoins.c +++ b/src/backend/optimizer/plan/analyzejoins.c @@ -42,6 +42,7 @@ static bool rel_is_distinct_for(PlannerInfo *root, RelOptInfo *rel, List *clause_list); static Oid distinct_col_search(int colno, List *colnos, List *opids); static bool is_innerrel_unique_for(PlannerInfo *root, + Relids joinrelids, Relids outerrelids, RelOptInfo *innerrel, JoinType jointype, @@ -565,7 +566,8 @@ reduce_unique_semijoins(PlannerInfo *root) innerrel->joininfo); /* Test whether the innerrel is unique for those clauses. */ - if (!innerrel_is_unique(root, sjinfo->min_lefthand, innerrel, + if (!innerrel_is_unique(root, + joinrelids, sjinfo->min_lefthand, innerrel, JOIN_SEMI, restrictlist, true)) continue; @@ -947,7 +949,8 @@ distinct_col_search(int colno, List *colnos, List *opids) * * We need an actual RelOptInfo for the innerrel, but it's sufficient to * identify the outerrel by its Relids. This asymmetry supports use of this - * function before joinrels have been built. + * function before joinrels have been built. (The caller is expected to + * also supply the joinrelids, just to save recalculating that.) * * The proof must be made based only on clauses that will be "joinquals" * rather than "otherquals" at execution. For an inner join there's no @@ -966,6 +969,7 @@ distinct_col_search(int colno, List *colnos, List *opids) */ bool innerrel_is_unique(PlannerInfo *root, + Relids joinrelids, Relids outerrelids, RelOptInfo *innerrel, JoinType jointype, @@ -1014,7 +1018,7 @@ innerrel_is_unique(PlannerInfo *root, } /* No cached information, so try to make the proof. */ - if (is_innerrel_unique_for(root, outerrelids, innerrel, + if (is_innerrel_unique_for(root, joinrelids, outerrelids, innerrel, jointype, restrictlist)) { /* @@ -1073,12 +1077,12 @@ innerrel_is_unique(PlannerInfo *root, */ static bool is_innerrel_unique_for(PlannerInfo *root, + Relids joinrelids, Relids outerrelids, RelOptInfo *innerrel, JoinType jointype, List *restrictlist) { - Relids joinrelids = bms_union(outerrelids, innerrel->relids); List *clause_list = NIL; ListCell *lc; diff --git a/src/include/optimizer/cost.h b/src/include/optimizer/cost.h index d3269eae71..6e6d0d3c79 100644 --- a/src/include/optimizer/cost.h +++ b/src/include/optimizer/cost.h @@ -166,6 +166,7 @@ extern void cost_subplan(PlannerInfo *root, SubPlan *subplan, Plan *plan); extern void cost_qual_eval(QualCost *cost, List *quals, PlannerInfo *root); extern void cost_qual_eval_node(QualCost *cost, Node *qual, PlannerInfo *root); extern void compute_semi_anti_join_factors(PlannerInfo *root, + RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, diff --git a/src/include/optimizer/planmain.h b/src/include/optimizer/planmain.h index 7132c88242..c8ab0280d2 100644 --- a/src/include/optimizer/planmain.h +++ b/src/include/optimizer/planmain.h @@ -108,7 +108,7 @@ extern void reduce_unique_semijoins(PlannerInfo *root); extern bool query_supports_distinctness(Query *query); extern bool query_is_distinct_for(Query *query, List *colnos, List *opids); extern bool innerrel_is_unique(PlannerInfo *root, - Relids outerrelids, RelOptInfo *innerrel, + Relids joinrelids, Relids outerrelids, RelOptInfo *innerrel, JoinType jointype, List *restrictlist, bool force_cache); /*