diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2004-01-06 04:31:01 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2004-01-06 04:31:01 +0000 |
commit | b0c4a50bbbbd62c444cb3806a97c1e51e2249cfd (patch) | |
tree | 0816cf1d1cc2a28665e5de740a20c80afbc4f5e7 /src/backend/executor/nodeIndexscan.c | |
parent | fa559a86eec2ae90fd63fd7e6563e42f7dc619e0 (diff) | |
download | postgresql-b0c4a50bbbbd62c444cb3806a97c1e51e2249cfd.tar.gz postgresql-b0c4a50bbbbd62c444cb3806a97c1e51e2249cfd.zip |
Instead of rechecking lossy index operators by putting them into the
regular qpqual ('filter condition'), add special-purpose code to
nodeIndexscan.c to recheck them. This ends being almost no net addition
of code, because the removal of planner code balances out the extra
executor code, but it is significantly more efficient when a lossy
operator is involved in an OR indexscan. The old implementation had
to recheck the entire indexqual in such cases.
Diffstat (limited to 'src/backend/executor/nodeIndexscan.c')
-rw-r--r-- | src/backend/executor/nodeIndexscan.c | 49 |
1 files changed, 48 insertions, 1 deletions
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c index 0ece6c6702f..3a489b361c6 100644 --- a/src/backend/executor/nodeIndexscan.c +++ b/src/backend/executor/nodeIndexscan.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/nodeIndexscan.c,v 1.88 2003/12/30 20:05:05 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/nodeIndexscan.c,v 1.89 2004/01/06 04:31:01 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -99,7 +99,9 @@ IndexNext(IndexScanState *node) ExprContext *econtext; ScanDirection direction; IndexScanDescPtr scanDescs; + List **lossyQuals; IndexScanDesc scandesc; + List *lossyQual; Index scanrelid; HeapTuple tuple; TupleTableSlot *slot; @@ -120,6 +122,7 @@ IndexNext(IndexScanState *node) direction = ForwardScanDirection; } scanDescs = node->iss_ScanDescs; + lossyQuals = node->iss_LossyQuals; numIndices = node->iss_NumIndices; econtext = node->ss.ps.ps_ExprContext; slot = node->ss.ss_ScanTupleSlot; @@ -188,6 +191,8 @@ IndexNext(IndexScanState *node) while (indexNumber < numIndices) { scandesc = scanDescs[node->iss_IndexPtr]; + lossyQual = lossyQuals[node->iss_IndexPtr]; + while ((tuple = index_getnext(scandesc, direction)) != NULL) { /* @@ -202,6 +207,22 @@ IndexNext(IndexScanState *node) false); /* don't pfree */ /* + * If any of the index operators involved in this scan are lossy, + * recheck them by evaluating the original operator clauses. + */ + if (lossyQual) + { + econtext->ecxt_scantuple = slot; + ResetExprContext(econtext); + if (!ExecQual(lossyQual, econtext, false)) + { + /* Fails lossy op, so drop it and loop back for another */ + ExecClearTuple(slot); + continue; + } + } + + /* * If it's a multiple-index scan, make sure not to double-report * a tuple matched by more than one index. (See notes above.) */ @@ -615,6 +636,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate) List *indxqual; List *indxstrategy; List *indxsubtype; + List *indxlossy; List *indxid; int i; int numIndices; @@ -623,6 +645,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate) int *numScanKeys; RelationPtr indexDescs; IndexScanDescPtr scanDescs; + List **lossyQuals; ExprState ***runtimeKeyInfo; bool have_runtime_keys; RangeTblEntry *rtentry; @@ -680,6 +703,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate) indexstate->iss_RuntimeKeysReady = false; indexstate->iss_RelationDescs = NULL; indexstate->iss_ScanDescs = NULL; + indexstate->iss_LossyQuals = NULL; /* * get the index node information @@ -699,6 +723,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate) scanKeys = (ScanKey *) palloc(numIndices * sizeof(ScanKey)); indexDescs = (RelationPtr) palloc(numIndices * sizeof(Relation)); scanDescs = (IndexScanDescPtr) palloc(numIndices * sizeof(IndexScanDesc)); + lossyQuals = (List **) palloc0(numIndices * sizeof(List *)); /* * initialize space for runtime key info (may not be needed) @@ -712,11 +737,13 @@ ExecInitIndexScan(IndexScan *node, EState *estate) indxqual = node->indxqual; indxstrategy = node->indxstrategy; indxsubtype = node->indxsubtype; + indxlossy = node->indxlossy; for (i = 0; i < numIndices; i++) { List *quals; List *strategies; List *subtypes; + List *lossyflags; int n_keys; ScanKey scan_keys; ExprState **run_keys; @@ -728,6 +755,8 @@ ExecInitIndexScan(IndexScan *node, EState *estate) indxstrategy = lnext(indxstrategy); subtypes = lfirst(indxsubtype); indxsubtype = lnext(indxsubtype); + lossyflags = lfirst(indxlossy); + indxlossy = lnext(indxlossy); n_keys = length(quals); scan_keys = (n_keys <= 0) ? (ScanKey) NULL : (ScanKey) palloc(n_keys * sizeof(ScanKeyData)); @@ -747,6 +776,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate) AttrNumber varattno; /* att number used in scan */ StrategyNumber strategy; /* op's strategy number */ Oid subtype; /* op's strategy subtype */ + int lossy; /* op's recheck flag */ RegProcedure opfuncid; /* operator proc id used in scan */ Datum scanvalue; /* value used in scan (if const) */ @@ -759,6 +789,8 @@ ExecInitIndexScan(IndexScan *node, EState *estate) strategies = lnext(strategies); subtype = lfirsto(subtypes); subtypes = lnext(subtypes); + lossy = lfirsti(lossyflags); + lossyflags = lnext(lossyflags); if (!IsA(clause, OpExpr)) elog(ERROR, "indxqual is not an OpExpr"); @@ -839,6 +871,20 @@ ExecInitIndexScan(IndexScan *node, EState *estate) subtype, /* strategy subtype */ opfuncid, /* reg proc to use */ scanvalue); /* constant */ + + /* + * If this operator is lossy, add its indxqualorig expression + * to the list of quals to recheck. The nth() calls here could + * be avoided by chasing the lists in parallel to all the other + * lists, but since lossy operators are very uncommon, it's + * probably a waste of time to do so. + */ + if (lossy) + { + lossyQuals[i] = lappend(lossyQuals[i], + nth(j, + (List *) nth(i, indexstate->indxqualorig))); + } } /* @@ -928,6 +974,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate) indexstate->iss_RelationDescs = indexDescs; indexstate->iss_ScanDescs = scanDescs; + indexstate->iss_LossyQuals = lossyQuals; /* * Initialize result tuple type and projection info. |