Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit60be6da

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 parent78296c2 commit60be6da

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-
intiptr;
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+
returnslot;
151154
}
152155

153156
tuple=&(indexstate->iss_htup);
@@ -189,14 +192,14 @@ IndexNext(IndexScan *node)
189192
{
190193
boolprev_matches= false;
191194
intprev_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-
returnslot;
234-
else
235-
ExecClearTuple(slot);
237+
returnslot;/* 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
intj;
@@ -709,7 +714,8 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
709714
ScanKeyscan_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 anOper!");
752+
if (!IsA(clause,Expr)|| !IsA(op,Oper))
753+
elog(ERROR,"ExecInitIndexScan:indxqual not anopclause!");
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-
OidindexOid;
1070-
1071-
indexOid= (Oid)nthi(i,indxid);
1075+
OidindexOid= (Oid)nthi(i,indxid);
10721076

10731077
if (indexOid!=0)
10741078
{

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp