Commit 1fcd4b7a authored by Tom Lane's avatar Tom Lane

While determining the filter clauses for an index scan (either plain

or bitmap), use pred_test to be a little smarter about cases where a
filter clause is logically unnecessary.  This may be overkill for the
plain indexscan case, but it's definitely useful for OR'd bitmap scans.
parent 79a1b002
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.178 2005/04/25 01:30:13 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.179 2005/04/25 03:58:29 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -500,8 +500,14 @@ choose_bitmap_and(Query *root, RelOptInfo *rel, List *paths) ...@@ -500,8 +500,14 @@ choose_bitmap_and(Query *root, RelOptInfo *rel, List *paths)
* And we consider an index redundant if all its index conditions were * And we consider an index redundant if all its index conditions were
* already used by earlier indexes. (We could use pred_test() to have * already used by earlier indexes. (We could use pred_test() to have
* a more intelligent, but much more expensive, check --- but in most * a more intelligent, but much more expensive, check --- but in most
* cases simple equality should suffice, since after all the index * cases simple pointer equality should suffice, since after all the
* conditions are all coming from the same query clauses.) * index conditions are all coming from the same RestrictInfo lists.)
*
* XXX is there any risk of throwing away a useful partial index here
* because we don't explicitly look at indpred? At least in simple
* cases, the partial index will sort before competing non-partial
* indexes and so it makes the right choice, but perhaps we need to
* work harder.
*/ */
/* Convert list to array so we can apply qsort */ /* Convert list to array so we can apply qsort */
...@@ -530,7 +536,7 @@ choose_bitmap_and(Query *root, RelOptInfo *rel, List *paths) ...@@ -530,7 +536,7 @@ choose_bitmap_and(Query *root, RelOptInfo *rel, List *paths)
if (IsA(newpath, IndexPath)) if (IsA(newpath, IndexPath))
{ {
newqual = ((IndexPath *) newpath)->indexclauses; newqual = ((IndexPath *) newpath)->indexclauses;
if (list_difference(newqual, qualsofar) == NIL) if (list_difference_ptr(newqual, qualsofar) == NIL)
continue; /* redundant */ continue; /* redundant */
} }
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.186 2005/04/25 02:14:47 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.187 2005/04/25 03:58:30 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -720,6 +720,7 @@ create_indexscan_plan(Query *root, ...@@ -720,6 +720,7 @@ create_indexscan_plan(Query *root,
List *nonlossy_indexquals; List *nonlossy_indexquals;
List *indexstrategy; List *indexstrategy;
List *indexsubtype; List *indexsubtype;
ListCell *l;
IndexScan *scan_plan; IndexScan *scan_plan;
/* it should be a base rel... */ /* it should be a base rel... */
...@@ -768,13 +769,31 @@ create_indexscan_plan(Query *root, ...@@ -768,13 +769,31 @@ create_indexscan_plan(Query *root,
* checked (either by the index itself, or by nodeIndexscan.c), but if * checked (either by the index itself, or by nodeIndexscan.c), but if
* there are any "special" operators involved then they must be included * there are any "special" operators involved then they must be included
* in qpqual. Also, any lossy index operators must be rechecked in * in qpqual. Also, any lossy index operators must be rechecked in
* the qpqual. The upshot is that qpquals must contain scan_clauses * the qpqual. The upshot is that qpqual must contain scan_clauses
* minus whatever appears in nonlossy_indexquals. * minus whatever appears in nonlossy_indexquals.
*
* In normal cases simple pointer equality checks will be enough to
* spot duplicate RestrictInfos, so we try that first. In some situations
* (particularly with OR'd index conditions) we may have scan_clauses
* that are not equal to, but are logically implied by, the index quals;
* so we also try a pred_test() check to see if we can discard quals
* that way.
*
* While at it, we strip off the RestrictInfos to produce a list of
* plain expressions.
*/ */
qpqual = list_difference_ptr(scan_clauses, nonlossy_indexquals); qpqual = NIL;
foreach(l, scan_clauses)
{
RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
/* Reduce RestrictInfo list to bare expressions */ Assert(IsA(rinfo, RestrictInfo));
qpqual = get_actual_clauses(qpqual); if (list_member_ptr(nonlossy_indexquals, rinfo))
continue;
if (pred_test(list_make1(rinfo->clause), nonlossy_indexquals))
continue;
qpqual = lappend(qpqual, rinfo->clause);
}
/* Sort clauses into best execution order */ /* Sort clauses into best execution order */
qpqual = order_qual_clauses(root, qpqual); qpqual = order_qual_clauses(root, qpqual);
...@@ -813,6 +832,7 @@ create_bitmap_scan_plan(Query *root, ...@@ -813,6 +832,7 @@ create_bitmap_scan_plan(Query *root,
List *bitmapqualorig; List *bitmapqualorig;
List *indexquals; List *indexquals;
List *qpqual; List *qpqual;
ListCell *l;
BitmapHeapScan *scan_plan; BitmapHeapScan *scan_plan;
/* it should be a base rel... */ /* it should be a base rel... */
...@@ -848,13 +868,23 @@ create_bitmap_scan_plan(Query *root, ...@@ -848,13 +868,23 @@ create_bitmap_scan_plan(Query *root,
* must be added to qpqual. The upshot is that qpquals must contain * must be added to qpqual. The upshot is that qpquals must contain
* scan_clauses minus whatever appears in indexquals. * scan_clauses minus whatever appears in indexquals.
* *
* NOTE: when there are OR clauses in indexquals, the simple equality * In normal cases simple equal() checks will be enough to spot duplicate
* check used by list_difference will only detect matches in case of * clauses, so we try that first. In some situations (particularly with
* chance equality of the OR subclause ordering. This is probably all * OR'd index conditions) we may have scan_clauses that are not equal to,
* right for now because that order will match what's in scan_clauses * but are logically implied by, the index quals; so we also try a
* ... but perhaps we need more smarts here. * pred_test() check to see if we can discard quals that way.
*/ */
qpqual = list_difference(scan_clauses, indexquals); qpqual = NIL;
foreach(l, scan_clauses)
{
Node *clause = (Node *) lfirst(l);
if (list_member(indexquals, clause))
continue;
if (pred_test(list_make1(clause), indexquals))
continue;
qpqual = lappend(qpqual, clause);
}
/* Sort clauses into best execution order */ /* Sort clauses into best execution order */
qpqual = order_qual_clauses(root, qpqual); qpqual = order_qual_clauses(root, qpqual);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment