mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-10-02 05:41:20 +02:00
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 TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node);
|
||||||
static void bitgetpage(HeapScanDesc scan, TBMIterateResult *tbmres);
|
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;
|
TIDBitmap *tbm;
|
||||||
TBMIterator *tbmiterator;
|
TBMIterator *tbmiterator;
|
||||||
TBMIterateResult *tbmres;
|
TBMIterateResult *tbmres;
|
||||||
|
|
||||||
#ifdef USE_PREFETCH
|
|
||||||
TBMIterator *prefetch_iterator;
|
|
||||||
#endif
|
|
||||||
OffsetNumber targoffset;
|
OffsetNumber targoffset;
|
||||||
TupleTableSlot *slot;
|
TupleTableSlot *slot;
|
||||||
|
|
||||||
@ -85,9 +86,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
|
|||||||
tbm = node->tbm;
|
tbm = node->tbm;
|
||||||
tbmiterator = node->tbmiterator;
|
tbmiterator = node->tbmiterator;
|
||||||
tbmres = node->tbmres;
|
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
|
* If we haven't yet performed the underlying index scan, do it, and begin
|
||||||
@ -115,7 +113,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
|
|||||||
#ifdef USE_PREFETCH
|
#ifdef USE_PREFETCH
|
||||||
if (node->prefetch_maximum > 0)
|
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_pages = 0;
|
||||||
node->prefetch_target = -1;
|
node->prefetch_target = -1;
|
||||||
}
|
}
|
||||||
@ -139,21 +137,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_PREFETCH
|
BitmapAdjustPrefetchIterator(node, tbmres);
|
||||||
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 */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ignore any claimed entries past what we think is the end of the
|
* Ignore any claimed entries past what we think is the end of the
|
||||||
@ -182,23 +166,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
|
|||||||
*/
|
*/
|
||||||
scan->rs_cindex = 0;
|
scan->rs_cindex = 0;
|
||||||
|
|
||||||
#ifdef USE_PREFETCH
|
/* Adjust the prefetch target */
|
||||||
|
BitmapAdjustPrefetchTarget(node);
|
||||||
/*
|
|
||||||
* 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 */
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -227,8 +196,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_PREFETCH
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We issue prefetch requests *after* fetching the current page to try
|
* We issue prefetch requests *after* fetching the current page to try
|
||||||
* to avoid having prefetching interfere with the main I/O. Also, this
|
* 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
|
* to do on the current page, else we may uselessly prefetch the same
|
||||||
* page we are just about to request for real.
|
* page we are just about to request for real.
|
||||||
*/
|
*/
|
||||||
if (prefetch_iterator)
|
BitmapPrefetch(node, scan);
|
||||||
{
|
|
||||||
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 */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Okay to fetch the tuple
|
* Okay to fetch the tuple
|
||||||
@ -411,6 +361,84 @@ bitgetpage(HeapScanDesc scan, TBMIterateResult *tbmres)
|
|||||||
scan->rs_ntuples = ntup;
|
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
|
* BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user