diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2019-02-09 17:30:43 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2019-02-09 17:30:43 -0500 |
commit | 1a8d5afb0dfc5d0dcc6eda0656a34cb1f0cf0bdf (patch) | |
tree | 05bf4d168989789a2b4bbf5c62590c75a0267df7 /src/backend/optimizer/path/equivclass.c | |
parent | 6401583863eaf83624994908911350b03f9978ae (diff) |
Refactor the representation of indexable clauses in IndexPaths.
In place of three separate but interrelated lists (indexclauses,
indexquals, and indexqualcols), an IndexPath now has one list
"indexclauses" of IndexClause nodes. This holds basically the same
information as before, but in a more useful format: in particular, there
is now a clear connection between an indexclause (an original restriction
clause from WHERE or JOIN/ON) and the indexquals (directly usable index
conditions) derived from it.
We also change the ground rules a bit by mandating that clause commutation,
if needed, be done up-front so that what is stored in the indexquals list
is always directly usable as an index condition. This gets rid of repeated
re-determination of which side of the clause is the indexkey during costing
and plan generation, as well as repeated lookups of the commutator
operator. To minimize the added up-front cost, the typical case of
commuting a plain OpExpr is handled by a new special-purpose function
commute_restrictinfo(). For RowCompareExprs, generating the new clause
properly commuted to begin with is not really any more complex than before,
it's just different --- and we can save doing that work twice, as the
pretty-klugy original implementation did.
Tracking the connection between original and derived clauses lets us
also track explicitly whether the derived clauses are an exact or lossy
translation of the original. This provides a cheap solution to getting
rid of unnecessary rechecks of boolean index clauses, which previously
seemed like it'd be more expensive than it was worth.
Another pleasant (IMO) side-effect is that EXPLAIN now always shows
index clauses with the indexkey on the left; this seems less confusing.
This commit leaves expand_indexqual_conditions() and some related
functions in a slightly messy state. I didn't bother to change them
any more than minimally necessary to work with the new data structure,
because all that code is going to be refactored out of existence in
a follow-on patch.
Discussion: https://postgr.es/m/22182.1549124950@sss.pgh.pa.us
Diffstat (limited to 'src/backend/optimizer/path/equivclass.c')
-rw-r--r-- | src/backend/optimizer/path/equivclass.c | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/src/backend/optimizer/path/equivclass.c b/src/backend/optimizer/path/equivclass.c index 3454f129122..23792508b7b 100644 --- a/src/backend/optimizer/path/equivclass.c +++ b/src/backend/optimizer/path/equivclass.c @@ -2511,3 +2511,40 @@ is_redundant_derived_clause(RestrictInfo *rinfo, List *clauselist) return false; } + +/* + * is_redundant_with_indexclauses + * Test whether rinfo is redundant with any clause in the IndexClause + * list. Here, for convenience, we test both simple identity and + * whether it is derived from the same EC as any member of the list. + */ +bool +is_redundant_with_indexclauses(RestrictInfo *rinfo, List *indexclauses) +{ + EquivalenceClass *parent_ec = rinfo->parent_ec; + ListCell *lc; + + foreach(lc, indexclauses) + { + IndexClause *iclause = lfirst_node(IndexClause, lc); + RestrictInfo *otherrinfo = iclause->rinfo; + + /* If indexclause is lossy, it won't enforce the condition exactly */ + if (iclause->lossy) + continue; + + /* Match if it's same clause (pointer equality should be enough) */ + if (rinfo == otherrinfo) + return true; + /* Match if derived from same EC */ + if (parent_ec && otherrinfo->parent_ec == parent_ec) + return true; + + /* + * No need to look at the derived clauses in iclause->indexquals; they + * couldn't match if the parent clause didn't. + */ + } + + return false; +} |