From ac2b09508834c9d6b7ec9467e876213b0304c792 Mon Sep 17 00:00:00 2001 From: Simon Riggs Date: Thu, 6 Apr 2017 19:10:51 -0400 Subject: [PATCH] Reset API of clause_selectivity() Discussion: https://postgr.es/m/CAKJS1f9yurJQW9pdnzL+rmOtsp2vOytkpXKGnMFJEO-qz5O5eA@mail.gmail.com --- contrib/file_fdw/file_fdw.c | 1 - contrib/postgres_fdw/postgres_fdw.c | 5 +- src/backend/optimizer/path/clausesel.c | 69 +++++++++++++++++++------- src/backend/optimizer/path/costsize.c | 25 ++++------ src/backend/optimizer/util/orclauses.c | 4 +- src/backend/statistics/dependencies.c | 4 +- src/backend/utils/adt/selfuncs.c | 20 +++----- src/include/optimizer/cost.h | 6 +-- 8 files changed, 74 insertions(+), 60 deletions(-) diff --git a/contrib/file_fdw/file_fdw.c b/contrib/file_fdw/file_fdw.c index 7414c16128..277639f6e9 100644 --- a/contrib/file_fdw/file_fdw.c +++ b/contrib/file_fdw/file_fdw.c @@ -1013,7 +1013,6 @@ estimate_size(PlannerInfo *root, RelOptInfo *baserel, baserel->baserestrictinfo, 0, JOIN_INNER, - NULL, NULL); nrows = clamp_row_est(nrows); diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c index a73d1a0bed..2851869932 100644 --- a/contrib/postgres_fdw/postgres_fdw.c +++ b/contrib/postgres_fdw/postgres_fdw.c @@ -591,7 +591,6 @@ postgresGetForeignRelSize(PlannerInfo *root, fpinfo->local_conds, baserel->relid, JOIN_INNER, - NULL, NULL); cost_qual_eval(&fpinfo->local_conds_cost, fpinfo->local_conds, root); @@ -2573,7 +2572,6 @@ estimate_path_cost_size(PlannerInfo *root, local_param_join_conds, foreignrel->relid, JOIN_INNER, - NULL, NULL); local_sel *= fpinfo->local_conds_sel; @@ -4457,7 +4455,6 @@ postgresGetForeignJoinPaths(PlannerInfo *root, fpinfo->local_conds, 0, JOIN_INNER, - NULL, NULL); cost_qual_eval(&fpinfo->local_conds_cost, fpinfo->local_conds, root); @@ -4468,7 +4465,7 @@ postgresGetForeignJoinPaths(PlannerInfo *root, if (!fpinfo->use_remote_estimate) fpinfo->joinclause_sel = clauselist_selectivity(root, fpinfo->joinclauses, 0, fpinfo->jointype, - extra->sjinfo, NULL); + extra->sjinfo); /* Estimate costs for bare join relation */ estimate_path_cost_size(root, joinrel, NIL, NIL, &rows, diff --git a/src/backend/optimizer/path/clausesel.c b/src/backend/optimizer/path/clausesel.c index 1ba578130e..614c1d127c 100644 --- a/src/backend/optimizer/path/clausesel.c +++ b/src/backend/optimizer/path/clausesel.c @@ -41,7 +41,8 @@ typedef struct RangeQueryClause static void addRangeClause(RangeQueryClause **rqlist, Node *clause, bool varonleft, bool isLTsel, Selectivity s2); - +static RelOptInfo *find_relation_from_clauses(PlannerInfo *root, + List *clauses); /**************************************************************************** * ROUTINES TO COMPUTE SELECTIVITIES @@ -101,14 +102,14 @@ clauselist_selectivity(PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, - SpecialJoinInfo *sjinfo, - RelOptInfo *rel) + SpecialJoinInfo *sjinfo) { Selectivity s1 = 1.0; RangeQueryClause *rqlist = NULL; ListCell *l; Bitmapset *estimatedclauses = NULL; int listidx; + RelOptInfo *rel; /* * If there's exactly one clause, then extended statistics is futile at @@ -117,7 +118,14 @@ clauselist_selectivity(PlannerInfo *root, */ if (list_length(clauses) == 1) return clause_selectivity(root, (Node *) linitial(clauses), - varRelid, jointype, sjinfo, rel); + varRelid, jointype, sjinfo); + + /* + * Determine if these clauses reference a single relation. If so we might + * like to try applying any extended statistics which exist on it. + * Called many time during joins, so must return NULL quickly if not. + */ + rel = find_relation_from_clauses(root, clauses); /* * When a relation of RTE_RELATION is given as 'rel', we'll try to @@ -164,7 +172,7 @@ clauselist_selectivity(PlannerInfo *root, continue; /* Always compute the selectivity using clause_selectivity */ - s2 = clause_selectivity(root, clause, varRelid, jointype, sjinfo, rel); + s2 = clause_selectivity(root, clause, varRelid, jointype, sjinfo); /* * Check for being passed a RestrictInfo. @@ -417,6 +425,39 @@ addRangeClause(RangeQueryClause **rqlist, Node *clause, *rqlist = rqelem; } +/* + * find_relation_from_clauses + * Process each clause in 'clauses' and determine if all clauses + * reference only a single relation. If so return that relation, + * otherwise return NULL. + */ +static RelOptInfo * +find_relation_from_clauses(PlannerInfo *root, List *clauses) +{ + ListCell *l; + int relid; + int lastrelid = 0; + + foreach(l, clauses) + { + RestrictInfo *rinfo = (RestrictInfo *) lfirst(l); + + if (bms_get_singleton_member(rinfo->clause_relids, &relid)) + { + if (lastrelid != 0 && relid != lastrelid) + return NULL; /* relation not the same as last one */ + lastrelid = relid; + } + else + return NULL; /* multiple relations in clause */ + } + + if (lastrelid != 0) + return find_base_rel(root, lastrelid); + + return NULL; /* no clauses */ +} + /* * bms_is_subset_singleton * @@ -529,8 +570,7 @@ clause_selectivity(PlannerInfo *root, Node *clause, int varRelid, JoinType jointype, - SpecialJoinInfo *sjinfo, - RelOptInfo *rel) + SpecialJoinInfo *sjinfo) { Selectivity s1 = 0.5; /* default for any unhandled clause type */ RestrictInfo *rinfo = NULL; @@ -650,8 +690,7 @@ clause_selectivity(PlannerInfo *root, (Node *) get_notclausearg((Expr *) clause), varRelid, jointype, - sjinfo, - rel); + sjinfo); } else if (and_clause(clause)) { @@ -660,8 +699,7 @@ clause_selectivity(PlannerInfo *root, ((BoolExpr *) clause)->args, varRelid, jointype, - sjinfo, - rel); + sjinfo); } else if (or_clause(clause)) { @@ -680,8 +718,7 @@ clause_selectivity(PlannerInfo *root, (Node *) lfirst(arg), varRelid, jointype, - sjinfo, - rel); + sjinfo); s1 = s1 + s2 - s1 * s2; } @@ -774,8 +811,7 @@ clause_selectivity(PlannerInfo *root, (Node *) ((RelabelType *) clause)->arg, varRelid, jointype, - sjinfo, - rel); + sjinfo); } else if (IsA(clause, CoerceToDomain)) { @@ -784,8 +820,7 @@ clause_selectivity(PlannerInfo *root, (Node *) ((CoerceToDomain *) clause)->arg, varRelid, jointype, - sjinfo, - rel); + sjinfo); } else { diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index bf0fb56ab0..ed07e2f655 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -3750,8 +3750,7 @@ compute_semi_anti_join_factors(PlannerInfo *root, joinquals, 0, jointype, - sjinfo, - NULL); + sjinfo); /* * Also get the normal inner-join selectivity of the join clauses. @@ -3774,8 +3773,7 @@ compute_semi_anti_join_factors(PlannerInfo *root, joinquals, 0, JOIN_INNER, - &norm_sjinfo, - NULL); + &norm_sjinfo); /* Avoid leaking a lot of ListCells */ if (jointype == JOIN_ANTI) @@ -3942,7 +3940,7 @@ approx_tuple_count(PlannerInfo *root, JoinPath *path, List *quals) Node *qual = (Node *) lfirst(l); /* Note that clause_selectivity will be able to cache its result */ - selec *= clause_selectivity(root, qual, 0, JOIN_INNER, &sjinfo, NULL); + selec *= clause_selectivity(root, qual, 0, JOIN_INNER, &sjinfo); } /* Apply it to the input relation sizes */ @@ -3978,8 +3976,7 @@ set_baserel_size_estimates(PlannerInfo *root, RelOptInfo *rel) rel->baserestrictinfo, 0, JOIN_INNER, - NULL, - rel); + NULL); rel->rows = clamp_row_est(nrows); @@ -4016,8 +4013,7 @@ get_parameterized_baserel_size(PlannerInfo *root, RelOptInfo *rel, allclauses, rel->relid, /* do not use 0! */ JOIN_INNER, - NULL, - rel); + NULL); nrows = clamp_row_est(nrows); /* For safety, make sure result is not more than the base estimate */ if (nrows > rel->rows) @@ -4183,14 +4179,12 @@ calc_joinrel_size_estimate(PlannerInfo *root, joinquals, 0, jointype, - sjinfo, - NULL); + sjinfo); pselec = clauselist_selectivity(root, pushedquals, 0, jointype, - sjinfo, - NULL); + sjinfo); /* Avoid leaking a lot of ListCells */ list_free(joinquals); @@ -4202,8 +4196,7 @@ calc_joinrel_size_estimate(PlannerInfo *root, restrictlist, 0, jointype, - sjinfo, - NULL); + sjinfo); pselec = 0.0; /* not used, keep compiler quiet */ } @@ -4498,7 +4491,7 @@ get_foreign_key_join_selectivity(PlannerInfo *root, Selectivity csel; csel = clause_selectivity(root, (Node *) rinfo, - 0, jointype, sjinfo, NULL); + 0, jointype, sjinfo); thisfksel = Min(thisfksel, csel); } fkselec *= thisfksel; diff --git a/src/backend/optimizer/util/orclauses.c b/src/backend/optimizer/util/orclauses.c index 735697d2f3..9cbcaedb75 100644 --- a/src/backend/optimizer/util/orclauses.c +++ b/src/backend/optimizer/util/orclauses.c @@ -280,7 +280,7 @@ consider_new_or_clause(PlannerInfo *root, RelOptInfo *rel, * saving work later.) */ or_selec = clause_selectivity(root, (Node *) or_rinfo, - 0, JOIN_INNER, NULL, rel); + 0, JOIN_INNER, NULL); /* * The clause is only worth adding to the query if it rejects a useful @@ -344,7 +344,7 @@ consider_new_or_clause(PlannerInfo *root, RelOptInfo *rel, /* Compute inner-join size */ orig_selec = clause_selectivity(root, (Node *) join_or_rinfo, - 0, JOIN_INNER, &sjinfo, NULL); + 0, JOIN_INNER, &sjinfo); /* And hack cached selectivity so join size remains the same */ join_or_rinfo->norm_selec = orig_selec / or_selec; diff --git a/src/backend/statistics/dependencies.c b/src/backend/statistics/dependencies.c index 159ddb8723..1a90e4b715 100644 --- a/src/backend/statistics/dependencies.c +++ b/src/backend/statistics/dependencies.c @@ -1050,8 +1050,8 @@ dependencies_clauselist_selectivity(PlannerInfo *root, { clause = (Node *) lfirst(l); - s2 = clause_selectivity(root, clause, varRelid, jointype, sjinfo, - NULL); /* don't try to use ext stats */ + s2 = clause_selectivity(root, clause, varRelid, jointype, + sjinfo); /* mark this one as done, so we don't touch it again. */ *estimatedclauses = bms_add_member(*estimatedclauses, listidx); diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index b6893e22bf..51c50eff50 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -1634,17 +1634,13 @@ booltestsel(PlannerInfo *root, BoolTestType booltesttype, Node *arg, case IS_NOT_FALSE: selec = (double) clause_selectivity(root, arg, varRelid, - jointype, - sjinfo, - NULL); + jointype, sjinfo); break; case IS_FALSE: case IS_NOT_TRUE: selec = 1.0 - (double) clause_selectivity(root, arg, varRelid, - jointype, - sjinfo, - NULL); + jointype, sjinfo); break; default: elog(ERROR, "unrecognized booltesttype: %d", @@ -6441,8 +6437,7 @@ genericcostestimate(PlannerInfo *root, indexSelectivity = clauselist_selectivity(root, selectivityQuals, index->rel->relid, JOIN_INNER, - NULL, - index->rel); + NULL); /* * If caller didn't give us an estimate, estimate the number of index @@ -6763,8 +6758,7 @@ btcostestimate(PlannerInfo *root, IndexPath *path, double loop_count, btreeSelectivity = clauselist_selectivity(root, selectivityQuals, index->rel->relid, JOIN_INNER, - NULL, - index->rel); + NULL); numIndexTuples = btreeSelectivity * index->rel->tuples; /* @@ -7523,8 +7517,7 @@ gincostestimate(PlannerInfo *root, IndexPath *path, double loop_count, *indexSelectivity = clauselist_selectivity(root, selectivityQuals, index->rel->relid, JOIN_INNER, - NULL, - index->rel); + NULL); /* fetch estimated page cost for tablespace containing index */ get_tablespace_page_costs(index->reltablespace, @@ -7854,8 +7847,7 @@ brincostestimate(PlannerInfo *root, IndexPath *path, double loop_count, qualSelectivity = clauselist_selectivity(root, indexQuals, baserel->relid, - JOIN_INNER, NULL, - baserel); + JOIN_INNER, NULL); /* work out the actual number of ranges in the index */ indexRanges = Max(ceil((double) baserel->pages / statsData.pagesPerRange), diff --git a/src/include/optimizer/cost.h b/src/include/optimizer/cost.h index 81a84b5494..6909359bcf 100644 --- a/src/include/optimizer/cost.h +++ b/src/include/optimizer/cost.h @@ -203,14 +203,12 @@ extern Selectivity clauselist_selectivity(PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, - SpecialJoinInfo *sjinfo, - RelOptInfo *rel); + SpecialJoinInfo *sjinfo); extern Selectivity clause_selectivity(PlannerInfo *root, Node *clause, int varRelid, JoinType jointype, - SpecialJoinInfo *sjinfo, - RelOptInfo *rel); + SpecialJoinInfo *sjinfo); extern void cost_gather_merge(GatherMergePath *path, PlannerInfo *root, RelOptInfo *rel, ParamPathInfo *param_info, Cost input_startup_cost, Cost input_total_cost,