mirror of
https://github.com/postgres/postgres.git
synced 2025-07-03 20:02:46 +03:00
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.
This commit is contained in:
@ -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)
|
|||||||
* 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)
|
|||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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,
|
|||||||
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,
|
|||||||
* 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,
|
|||||||
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,
|
|||||||
* 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);
|
||||||
|
Reference in New Issue
Block a user