Refactor bitmap heap scan in preparation for parallel support.
The final patch will be less messy if the prefetching support is a bit better isolated, so do that. Dilip Kumar, with some changes by me. The larger patch set of which this is a part has been reviewed and tested by (at least) Andres Freund, Amit Khandekar, Tushar Ahuja, Rafia Sabih, Haribabu Kommi, and Thomas Munro.
This commit is contained in:
parent
3c3bb99330
commit
9e0fe09fc5
|
@ -53,6 +53,11 @@
|
|||
|
||||
static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
|
||||
static void bitgetpage(HeapScanDesc scan, TBMIterateResult *tbmres);
|
||||
static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
|
||||
TBMIterateResult *tbmres);
|
||||
static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node);
|
||||
static inline void BitmapPrefetch(BitmapHeapScanState *node,
|
||||
HeapScanDesc scan);
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
|
@ -69,10 +74,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
|
|||
TIDBitmap *tbm;
|
||||
TBMIterator *tbmiterator;
|
||||
TBMIterateResult *tbmres;
|
||||
|
||||
#ifdef USE_PREFETCH
|
||||
TBMIterator *prefetch_iterator;
|
||||
#endif
|
||||
OffsetNumber targoffset;
|
||||
TupleTableSlot *slot;
|
||||
|
||||
|
@ -85,9 +86,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
|
|||
tbm = node->tbm;
|
||||
tbmiterator = node->tbmiterator;
|
||||
tbmres = node->tbmres;
|
||||
#ifdef USE_PREFETCH
|
||||
prefetch_iterator = node->prefetch_iterator;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If we haven't yet performed the underlying index scan, do it, and begin
|
||||
|
@ -115,7 +113,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
|
|||
#ifdef USE_PREFETCH
|
||||
if (node->prefetch_maximum > 0)
|
||||
{
|
||||
node->prefetch_iterator = prefetch_iterator = tbm_begin_iterate(tbm);
|
||||
node->prefetch_iterator = tbm_begin_iterate(tbm);
|
||||
node->prefetch_pages = 0;
|
||||
node->prefetch_target = -1;
|
||||
}
|
||||
|
@ -139,21 +137,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
|
|||
break;
|
||||
}
|
||||
|
||||
#ifdef USE_PREFETCH
|
||||
if (node->prefetch_pages > 0)
|
||||
{
|
||||
/* The main iterator has closed the distance by one page */
|
||||
node->prefetch_pages--;
|
||||
}
|
||||
else if (prefetch_iterator)
|
||||
{
|
||||
/* Do not let the prefetch iterator get behind the main one */
|
||||
TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
|
||||
|
||||
if (tbmpre == NULL || tbmpre->blockno != tbmres->blockno)
|
||||
elog(ERROR, "prefetch and main iterators are out of sync");
|
||||
}
|
||||
#endif /* USE_PREFETCH */
|
||||
BitmapAdjustPrefetchIterator(node, tbmres);
|
||||
|
||||
/*
|
||||
* Ignore any claimed entries past what we think is the end of the
|
||||
|
@ -182,23 +166,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
|
|||
*/
|
||||
scan->rs_cindex = 0;
|
||||
|
||||
#ifdef USE_PREFETCH
|
||||
|
||||
/*
|
||||
* Increase prefetch target if it's not yet at the max. Note that
|
||||
* we will increase it to zero after fetching the very first
|
||||
* page/tuple, then to one after the second tuple is fetched, then
|
||||
* it doubles as later pages are fetched.
|
||||
*/
|
||||
if (node->prefetch_target >= node->prefetch_maximum)
|
||||
/* don't increase any further */ ;
|
||||
else if (node->prefetch_target >= node->prefetch_maximum / 2)
|
||||
node->prefetch_target = node->prefetch_maximum;
|
||||
else if (node->prefetch_target > 0)
|
||||
node->prefetch_target *= 2;
|
||||
else
|
||||
node->prefetch_target++;
|
||||
#endif /* USE_PREFETCH */
|
||||
/* Adjust the prefetch target */
|
||||
BitmapAdjustPrefetchTarget(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -227,8 +196,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
|
|||
continue;
|
||||
}
|
||||
|
||||
#ifdef USE_PREFETCH
|
||||
|
||||
/*
|
||||
* We issue prefetch requests *after* fetching the current page to try
|
||||
* to avoid having prefetching interfere with the main I/O. Also, this
|
||||
|
@ -236,24 +203,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
|
|||
* to do on the current page, else we may uselessly prefetch the same
|
||||
* page we are just about to request for real.
|
||||
*/
|
||||
if (prefetch_iterator)
|
||||
{
|
||||
while (node->prefetch_pages < node->prefetch_target)
|
||||
{
|
||||
TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
|
||||
|
||||
if (tbmpre == NULL)
|
||||
{
|
||||
/* No more pages to prefetch */
|
||||
tbm_end_iterate(prefetch_iterator);
|
||||
node->prefetch_iterator = prefetch_iterator = NULL;
|
||||
break;
|
||||
}
|
||||
node->prefetch_pages++;
|
||||
PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
|
||||
}
|
||||
}
|
||||
#endif /* USE_PREFETCH */
|
||||
BitmapPrefetch(node, scan);
|
||||
|
||||
/*
|
||||
* Okay to fetch the tuple
|
||||
|
@ -411,6 +361,84 @@ bitgetpage(HeapScanDesc scan, TBMIterateResult *tbmres)
|
|||
scan->rs_ntuples = ntup;
|
||||
}
|
||||
|
||||
/*
|
||||
* BitmapAdjustPrefetchIterator - Adjust the prefetch iterator
|
||||
*/
|
||||
static inline void
|
||||
BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
|
||||
TBMIterateResult *tbmres)
|
||||
{
|
||||
#ifdef USE_PREFETCH
|
||||
TBMIterator *prefetch_iterator = node->prefetch_iterator;
|
||||
|
||||
if (node->prefetch_pages > 0)
|
||||
{
|
||||
/* The main iterator has closed the distance by one page */
|
||||
node->prefetch_pages--;
|
||||
}
|
||||
else if (prefetch_iterator)
|
||||
{
|
||||
/* Do not let the prefetch iterator get behind the main one */
|
||||
TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
|
||||
|
||||
if (tbmpre == NULL || tbmpre->blockno != tbmres->blockno)
|
||||
elog(ERROR, "prefetch and main iterators are out of sync");
|
||||
}
|
||||
#endif /* USE_PREFETCH */
|
||||
}
|
||||
|
||||
/*
|
||||
* BitmapAdjustPrefetchTarget - Adjust the prefetch target
|
||||
*
|
||||
* Increase prefetch target if it's not yet at the max. Note that
|
||||
* we will increase it to zero after fetching the very first
|
||||
* page/tuple, then to one after the second tuple is fetched, then
|
||||
* it doubles as later pages are fetched.
|
||||
*/
|
||||
static inline void
|
||||
BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
|
||||
{
|
||||
#ifdef USE_PREFETCH
|
||||
if (node->prefetch_target >= node->prefetch_maximum)
|
||||
/* don't increase any further */ ;
|
||||
else if (node->prefetch_target >= node->prefetch_maximum / 2)
|
||||
node->prefetch_target = node->prefetch_maximum;
|
||||
else if (node->prefetch_target > 0)
|
||||
node->prefetch_target *= 2;
|
||||
else
|
||||
node->prefetch_target++;
|
||||
#endif /* USE_PREFETCH */
|
||||
}
|
||||
|
||||
/*
|
||||
* BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target
|
||||
*/
|
||||
static inline void
|
||||
BitmapPrefetch(BitmapHeapScanState *node, HeapScanDesc scan)
|
||||
{
|
||||
#ifdef USE_PREFETCH
|
||||
TBMIterator *prefetch_iterator = node->prefetch_iterator;
|
||||
|
||||
if (prefetch_iterator)
|
||||
{
|
||||
while (node->prefetch_pages < node->prefetch_target)
|
||||
{
|
||||
TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
|
||||
|
||||
if (tbmpre == NULL)
|
||||
{
|
||||
/* No more pages to prefetch */
|
||||
tbm_end_iterate(prefetch_iterator);
|
||||
node->prefetch_iterator = NULL;
|
||||
break;
|
||||
}
|
||||
node->prefetch_pages++;
|
||||
PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
|
||||
}
|
||||
}
|
||||
#endif /* USE_PREFETCH */
|
||||
}
|
||||
|
||||
/*
|
||||
* BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue