@@ -65,7 +65,7 @@ GetScanLists(IndexScanDesc scan, Datum value)
65
65
/* Use procinfo from the index instead of scan key for performance */
66
66
distance = DatumGetFloat8 (so -> distfunc (so -> procinfo ,so -> collation ,PointerGetDatum (& list -> center ),value ));
67
67
68
- if (listCount < so -> probes )
68
+ if (listCount < so -> maxProbes )
69
69
{
70
70
IvfflatScanList * scanlist ;
71
71
@@ -78,7 +78,7 @@ GetScanLists(IndexScanDesc scan, Datum value)
78
78
pairingheap_add (so -> listQueue ,& scanlist -> ph_node );
79
79
80
80
/* Calculate max distance */
81
- if (listCount == so -> probes )
81
+ if (listCount == so -> maxProbes )
82
82
maxDistance = GetScanList (pairingheap_first (so -> listQueue ))-> distance ;
83
83
}
84
84
else if (distance < maxDistance )
@@ -102,6 +102,11 @@ GetScanLists(IndexScanDesc scan, Datum value)
102
102
103
103
UnlockReleaseBuffer (cbuf );
104
104
}
105
+
106
+ for (int i = listCount - 1 ;i >=0 ;i -- )
107
+ so -> listPages [i ]= GetScanList (pairingheap_remove_first (so -> listQueue ))-> startPage ;
108
+
109
+ Assert (pairingheap_is_empty (so -> listQueue ));
105
110
}
106
111
107
112
/*
@@ -114,11 +119,14 @@ GetScanItems(IndexScanDesc scan, Datum value)
114
119
TupleDesc tupdesc = RelationGetDescr (scan -> indexRelation );
115
120
double tuples = 0 ;
116
121
TupleTableSlot * slot = so -> vslot ;
122
+ int batchProbes = 0 ;
123
+
124
+ tuplesort_reset (so -> sortstate );
117
125
118
126
/* Search closest probes lists */
119
- while (! pairingheap_is_empty ( so -> listQueue ) )
127
+ while (so -> listIndex < so -> maxProbes && ( ++ batchProbes ) <= so -> probes )
120
128
{
121
- BlockNumber searchPage = GetScanList ( pairingheap_remove_first ( so -> listQueue )) -> startPage ;
129
+ BlockNumber searchPage = so -> listPages [ so -> listIndex ++ ] ;
122
130
123
131
/* Search all entry pages for list */
124
132
while (BlockNumberIsValid (searchPage ))
@@ -166,13 +174,17 @@ GetScanItems(IndexScanDesc scan, Datum value)
166
174
}
167
175
}
168
176
169
- if (tuples < 100 )
177
+ if (tuples < 100 && ivfflat_iterative_search == IVFFLAT_ITERATIVE_SEARCH_OFF )
170
178
ereport (DEBUG1 ,
171
179
(errmsg ("index scan found few tuples" ),
172
180
errdetail ("Index may have been created with little data." ),
173
181
errhint ("Recreate the index and possibly decrease lists." )));
174
182
175
183
tuplesort_performsort (so -> sortstate );
184
+
185
+ #if defined(IVFFLAT_MEMORY )
186
+ elog (INFO ,"memory: %zu MB" ,MemoryContextMemAllocated (CurrentMemoryContext , true) / (1024 * 1024 ));
187
+ #endif
176
188
}
177
189
178
190
/*
@@ -240,6 +252,7 @@ ivfflatbeginscan(Relation index, int nkeys, int norderbys)
240
252
int lists ;
241
253
int dimensions ;
242
254
int probes = ivfflat_probes ;
255
+ int maxProbes ;
243
256
244
257
scan = RelationGetIndexScan (index ,nkeys ,norderbys );
245
258
@@ -249,10 +262,21 @@ ivfflatbeginscan(Relation index, int nkeys, int norderbys)
249
262
if (probes > lists )
250
263
probes = lists ;
251
264
252
- so = (IvfflatScanOpaque )palloc (offsetof(IvfflatScanOpaqueData ,lists )+ probes * sizeof (IvfflatScanList ));
265
+ if (ivfflat_iterative_search != IVFFLAT_ITERATIVE_SEARCH_OFF )
266
+ {
267
+ if (ivfflat_iterative_search_max_probes == 0 )
268
+ maxProbes = lists ;
269
+ else
270
+ maxProbes = Min (ivfflat_iterative_search_max_probes ,lists );
271
+ }
272
+ else
273
+ maxProbes = probes ;
274
+
275
+ so = (IvfflatScanOpaque )palloc (offsetof(IvfflatScanOpaqueData ,lists )+ maxProbes * sizeof (IvfflatScanList ));
253
276
so -> typeInfo = IvfflatGetTypeInfo (index );
254
277
so -> first = true;
255
278
so -> probes = probes ;
279
+ so -> maxProbes = maxProbes ;
256
280
so -> dimensions = dimensions ;
257
281
258
282
/* Set support functions */
@@ -280,6 +304,8 @@ ivfflatbeginscan(Relation index, int nkeys, int norderbys)
280
304
so -> bas = GetAccessStrategy (BAS_BULKREAD );
281
305
282
306
so -> listQueue = pairingheap_allocate (CompareLists ,scan );
307
+ so -> listPages = palloc (maxProbes * sizeof (BlockNumber ));
308
+ so -> listIndex = 0 ;
283
309
284
310
scan -> opaque = so ;
285
311
@@ -294,11 +320,9 @@ ivfflatrescan(IndexScanDesc scan, ScanKey keys, int nkeys, ScanKey orderbys, int
294
320
{
295
321
IvfflatScanOpaque so = (IvfflatScanOpaque )scan -> opaque ;
296
322
297
- if (!so -> first )
298
- tuplesort_reset (so -> sortstate );
299
-
300
323
so -> first = true;
301
324
pairingheap_reset (so -> listQueue );
325
+ so -> listIndex = 0 ;
302
326
303
327
if (keys && scan -> numberOfKeys > 0 )
304
328
memmove (scan -> keyData ,keys ,scan -> numberOfKeys * sizeof (ScanKeyData ));
314
338
ivfflatgettuple (IndexScanDesc scan ,ScanDirection dir )
315
339
{
316
340
IvfflatScanOpaque so = (IvfflatScanOpaque )scan -> opaque ;
341
+ ItemPointer heaptid ;
342
+ bool isnull ;
317
343
318
344
/*
319
345
* Index can be used to scan backward, but Postgres doesn't support
@@ -341,28 +367,25 @@ ivfflatgettuple(IndexScanDesc scan, ScanDirection dir)
341
367
IvfflatBench ("GetScanLists" ,GetScanLists (scan ,value ));
342
368
IvfflatBench ("GetScanItems" ,GetScanItems (scan ,value ));
343
369
so -> first = false;
370
+ so -> value = value ;
344
371
345
- #if defined(IVFFLAT_MEMORY )
346
- elog (INFO ,"memory: %zu MB" ,MemoryContextMemAllocated (CurrentMemoryContext , true) / (1024 * 1024 ));
347
- #endif
348
-
349
- /* Clean up if we allocated a new value */
350
- if (value != scan -> orderByData -> sk_argument )
351
- pfree (DatumGetPointer (value ));
372
+ /* TODO clean up if we allocated a new value */
352
373
}
353
374
354
- if ( tuplesort_gettupleslot (so -> sortstate , true, false,so -> mslot ,NULL ))
375
+ while (! tuplesort_gettupleslot (so -> sortstate , true, false,so -> mslot ,NULL ))
355
376
{
356
- bool isnull ;
357
- ItemPointer heaptid = ( ItemPointer ) DatumGetPointer ( slot_getattr ( so -> mslot , 2 , & isnull )) ;
377
+ if ( so -> listIndex == so -> maxProbes )
378
+ return false ;
358
379
359
- scan -> xs_heaptid = * heaptid ;
360
- scan -> xs_recheck = false;
361
- scan -> xs_recheckorderby = false;
362
- return true;
380
+ IvfflatBench ("GetScanItems" ,GetScanItems (scan ,so -> value ));
363
381
}
364
382
365
- return false;
383
+ heaptid = (ItemPointer )DatumGetPointer (slot_getattr (so -> mslot ,2 ,& isnull ));
384
+
385
+ scan -> xs_heaptid = * heaptid ;
386
+ scan -> xs_recheck = false;
387
+ scan -> xs_recheckorderby = false;
388
+ return true;
366
389
}
367
390
368
391
/*
@@ -374,6 +397,7 @@ ivfflatendscan(IndexScanDesc scan)
374
397
IvfflatScanOpaque so = (IvfflatScanOpaque )scan -> opaque ;
375
398
376
399
pairingheap_free (so -> listQueue );
400
+ pfree (so -> listPages );
377
401
tuplesort_end (so -> sortstate );
378
402
FreeAccessStrategy (so -> bas );
379
403
FreeTupleDesc (so -> tupdesc );