mirror of
https://github.com/postgres/postgres.git
synced 2025-07-08 11:42:09 +03:00
Fix OR-index-scan planner to recognize that a partial index is usable
for scanning one term of an OR clause if the index's predicate is implied by that same OR clause term (possibly in conjunction with top-level WHERE clauses). Per recent example from Dawid Kuroczko, http://archives.postgresql.org/pgsql-performance/2004-10/msg00095.php Also, fix a very long-standing bug in index predicate testing, namely the bizarre ordering of decomposition of predicate and restriction clauses. AFAICS the correct way is to break down the predicate all the way, and then for each component term see if you can prove it from the entire restriction set. The original coding had a purely-implementation-artifact distinction between ANDing at the top level and ANDing below that, and proceeded to get the decomposition order wrong everywhere below the top level, with the result that even slightly complicated AND/OR predicates could not be proven. For instance, given create index foop on foo(f2) where f1=42 or f1=1 or (f1 = 11 and f2 = 55); the old code would fail to match this index to the query select * from foo where f1 = 11 and f2 = 55; when it obviously ought to match.
This commit is contained in:
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/orindxpath.c,v 1.62 2004/08/29 05:06:43 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/orindxpath.c,v 1.63 2004/10/11 22:56:56 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -355,15 +355,42 @@ best_or_subclause_index(Query *root,
|
||||
List *indexquals;
|
||||
Path subclause_path;
|
||||
|
||||
/* Ignore partial indexes that do not match the query */
|
||||
/*
|
||||
* Ignore partial indexes that do not match the query. If predOK
|
||||
* is true then the index's predicate is implied by top-level
|
||||
* restriction clauses, so we can use it. However, it might also
|
||||
* be implied by the current OR subclause (perhaps in conjunction
|
||||
* with the top-level clauses), in which case we can use it for this
|
||||
* particular scan.
|
||||
*
|
||||
* XXX this code is partially redundant with logic in
|
||||
* group_clauses_by_indexkey_for_or(); consider refactoring.
|
||||
*/
|
||||
if (index->indpred != NIL && !index->predOK)
|
||||
continue;
|
||||
{
|
||||
List *subclauserinfos;
|
||||
|
||||
if (and_clause((Node *) subclause))
|
||||
subclauserinfos = list_copy(((BoolExpr *) subclause)->args);
|
||||
else if (IsA(subclause, RestrictInfo))
|
||||
subclauserinfos = list_make1(subclause);
|
||||
else
|
||||
continue; /* probably can't happen */
|
||||
if (!pred_test(index->indpred,
|
||||
list_concat(subclauserinfos,
|
||||
rel->baserestrictinfo)))
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Collect index clauses usable with this index */
|
||||
indexclauses = group_clauses_by_indexkey_for_or(rel, index, subclause);
|
||||
|
||||
/* Ignore index if it doesn't match the subclause at all */
|
||||
if (indexclauses == NIL)
|
||||
/*
|
||||
* Ignore index if it doesn't match the subclause at all; except
|
||||
* that if it's a partial index, consider it anyway, since the
|
||||
* selectivity of the predicate alone might make the index useful.
|
||||
*/
|
||||
if (indexclauses == NIL && index->indpred == NIL)
|
||||
continue;
|
||||
|
||||
/* Convert clauses to indexquals the executor can handle */
|
||||
|
Reference in New Issue
Block a user