Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 60be6da

Browse files
committed
Replace nth() calls in inner loops with traversal of the list via
lnext, to eliminate O(N^2) behavior with lots of indexquals.
1 parent 78296c2 commit 60be6da

File tree

1 file changed

+32
-28
lines changed

1 file changed

+32
-28
lines changed

src/backend/executor/nodeIndexscan.c

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.45 2000/01/26 05:56:23 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.46 2000/02/05 23:19:44 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -124,7 +124,7 @@ IndexNext(IndexScan *node)
124124
if (estate->es_evTuple != NULL &&
125125
estate->es_evTuple[node->scan.scanrelid - 1] != NULL)
126126
{
127-
int iptr;
127+
List *qual;
128128

129129
ExecClearTuple(slot);
130130
if (estate->es_evTupleNull[node->scan.scanrelid - 1])
@@ -134,20 +134,23 @@ IndexNext(IndexScan *node)
134134
slot->val = estate->es_evTuple[node->scan.scanrelid - 1];
135135
slot->ttc_shouldFree = false;
136136

137-
for (iptr = 0; iptr < numIndices; iptr++)
137+
scanstate->cstate.cs_ExprContext->ecxt_scantuple = slot;
138+
139+
/* Does the tuple meet any of the OR'd indxqual conditions? */
140+
foreach(qual, node->indxqualorig)
138141
{
139-
scanstate->cstate.cs_ExprContext->ecxt_scantuple = slot;
140-
if (ExecQual(nth(iptr, node->indxqualorig),
142+
if (ExecQual((List *) lfirst(qual),
141143
scanstate->cstate.cs_ExprContext,
142144
false))
143145
break;
144146
}
145-
if (iptr == numIndices) /* would not be returned by indices */
147+
if (qual == NIL) /* would not be returned by indices */
146148
slot->val = NULL;
147149

148150
/* Flag for the next call that no more tuples */
149151
estate->es_evTupleNull[node->scan.scanrelid - 1] = true;
150-
return (slot);
152+
153+
return slot;
151154
}
152155

153156
tuple = &(indexstate->iss_htup);
@@ -189,14 +192,14 @@ IndexNext(IndexScan *node)
189192
{
190193
bool prev_matches = false;
191194
int prev_index;
195+
List *qual;
192196

193-
/* ----------------
197+
/*
194198
* store the scanned tuple in the scan tuple slot of
195199
* the scan state. Eventually we will only do this and not
196200
* return a tuple. Note: we pass 'false' because tuples
197201
* returned by amgetnext are pointers onto disk pages and
198202
* must not be pfree()'d.
199-
* ----------------
200203
*/
201204
ExecStoreTuple(tuple, /* tuple to store */
202205
slot, /* slot to store in */
@@ -211,28 +214,29 @@ IndexNext(IndexScan *node)
211214
ReleaseBuffer(buffer);
212215

213216
/*
214-
* We must check to see if the current tuple would have
215-
* been matched by an earlier index, so we don't double
216-
* report it. We do this by passing the tuple through
217-
* ExecQual and look for failure with all previous
218-
* qualifications.
217+
* We must check to see if the current tuple was already
218+
* matched by an earlier index, so we don't double-report it.
219+
* We do this by passing the tuple through ExecQual and
220+
* checking for failure with all previous qualifications.
219221
*/
222+
scanstate->cstate.cs_ExprContext->ecxt_scantuple = slot;
223+
qual = node->indxqualorig;
220224
for (prev_index = 0; prev_index < indexstate->iss_IndexPtr;
221225
prev_index++)
222226
{
223-
scanstate->cstate.cs_ExprContext->ecxt_scantuple = slot;
224-
if (ExecQual(nth(prev_index, node->indxqualorig),
227+
if (ExecQual((List *) lfirst(qual),
225228
scanstate->cstate.cs_ExprContext,
226229
false))
227230
{
228231
prev_matches = true;
229232
break;
230233
}
234+
qual = lnext(qual);
231235
}
232236
if (!prev_matches)
233-
return slot;
234-
else
235-
ExecClearTuple(slot);
237+
return slot; /* OK to return tuple */
238+
/* Duplicate tuple, so drop it and loop back for another */
239+
ExecClearTuple(slot);
236240
}
237241
}
238242
if (indexNumber < numIndices)
@@ -329,7 +333,6 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
329333
scanDescs = indexstate->iss_ScanDescs;
330334
scanKeys = indexstate->iss_ScanKeys;
331335
runtimeKeyInfo = (Pointer *) indexstate->iss_RuntimeKeyInfo;
332-
indxqual = node->indxqual;
333336
numScanKeys = indexstate->iss_NumScanKeys;
334337
indexstate->iss_IndexPtr = -1;
335338
if (ScanDirectionIsBackward(node->indxorderdir))
@@ -352,9 +355,11 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
352355
/*
353356
* get the index qualifications and recalculate the appropriate values
354357
*/
358+
indxqual = node->indxqual;
355359
for (i = 0; i < numIndices; i++)
356360
{
357-
qual = nth(i, indxqual);
361+
qual = lfirst(indxqual);
362+
indxqual = lnext(indxqual);
358363
n_keys = numScanKeys[i];
359364
scan_keys = (ScanKey) scanKeys[i];
360365

@@ -672,7 +677,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
672677
* ----------------
673678
*/
674679
indxid = node->indxid;
675-
indxqual = node->indxqual;
676680
numIndices = length(indxid);
677681
indexPtr = -1;
678682

@@ -701,6 +705,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
701705
* build the index scan keys from the index qualification
702706
* ----------------
703707
*/
708+
indxqual = node->indxqual;
704709
for (i = 0; i < numIndices; i++)
705710
{
706711
int j;
@@ -709,7 +714,8 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
709714
ScanKey scan_keys;
710715
int *run_keys;
711716

712-
qual = nth(i, indxqual);
717+
qual = lfirst(indxqual);
718+
indxqual = lnext(indxqual);
713719
n_keys = length(qual);
714720
scan_keys = (n_keys <= 0) ? NULL :
715721
(ScanKey) palloc(n_keys * sizeof(ScanKeyData));
@@ -743,8 +749,8 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
743749
clause = nth(j, qual);
744750

745751
op = (Oper *) clause->oper;
746-
if (!IsA(op, Oper))
747-
elog(ERROR, "ExecInitIndexScan: op not an Oper!");
752+
if (!IsA(clause, Expr) || !IsA(op, Oper))
753+
elog(ERROR, "ExecInitIndexScan: indxqual not an opclause!");
748754

749755
opid = op->opid;
750756

@@ -1066,9 +1072,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
10661072
*/
10671073
for (i = 0; i < numIndices; i++)
10681074
{
1069-
Oid indexOid;
1070-
1071-
indexOid = (Oid) nthi(i, indxid);
1075+
Oid indexOid = (Oid) nthi(i, indxid);
10721076

10731077
if (indexOid != 0)
10741078
{

0 commit comments

Comments
 (0)