summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Riggs2017-04-06 23:10:51 +0000
committerSimon Riggs2017-04-06 23:10:51 +0000
commitac2b09508834c9d6b7ec9467e876213b0304c792 (patch)
tree7105e1721f18f74a0fc974a708d36096cd2c99fe
parent255efa241f460ee4f4c4c98c8cdd7457807f3af9 (diff)
Reset API of clause_selectivity()
Discussion: https://postgr.es/m/CAKJS1f9yurJQW9pdnzL+rmOtsp2vOytkpXKGnMFJEO-qz5O5eA@mail.gmail.com
-rw-r--r--contrib/file_fdw/file_fdw.c1
-rw-r--r--contrib/postgres_fdw/postgres_fdw.c5
-rw-r--r--src/backend/optimizer/path/clausesel.c69
-rw-r--r--src/backend/optimizer/path/costsize.c25
-rw-r--r--src/backend/optimizer/util/orclauses.c4
-rw-r--r--src/backend/statistics/dependencies.c4
-rw-r--r--src/backend/utils/adt/selfuncs.c20
-rw-r--r--src/include/optimizer/cost.h6
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.
@@ -418,6 +426,39 @@ addRangeClause(RangeQueryClause **rqlist, Node *clause,
}
/*
+ * 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
*
* Same result as bms_is_subset(s, bms_make_singleton(x)),
@@ -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,