diff options
Diffstat (limited to 'src/backend/executor/nodeBitmapHeapscan.c')
-rw-r--r-- | src/backend/executor/nodeBitmapHeapscan.c | 96 |
1 files changed, 95 insertions, 1 deletions
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c index 880b9c9590e..2ba8b89ee35 100644 --- a/src/backend/executor/nodeBitmapHeapscan.c +++ b/src/backend/executor/nodeBitmapHeapscan.c @@ -21,7 +21,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/nodeBitmapHeapscan.c,v 1.32 2009/01/10 21:08:36 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/nodeBitmapHeapscan.c,v 1.33 2009/01/12 05:10:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -67,6 +67,7 @@ BitmapHeapNext(BitmapHeapScanState *node) TIDBitmap *tbm; TBMIterator *tbmiterator; TBMIterateResult *tbmres; + TBMIterator *prefetch_iterator; OffsetNumber targoffset; TupleTableSlot *slot; @@ -81,6 +82,7 @@ BitmapHeapNext(BitmapHeapScanState *node) tbm = node->tbm; tbmiterator = node->tbmiterator; tbmres = node->tbmres; + prefetch_iterator = node->prefetch_iterator; /* * Check if we are evaluating PlanQual for tuple of this relation. @@ -114,6 +116,15 @@ BitmapHeapNext(BitmapHeapScanState *node) /* * If we haven't yet performed the underlying index scan, do it, and * begin the iteration over the bitmap. + * + * For prefetching, we use *two* iterators, one for the pages we are + * actually scanning and another that runs ahead of the first for + * prefetching. node->prefetch_pages tracks exactly how many pages + * ahead the prefetch iterator is. Also, node->prefetch_target tracks + * the desired prefetch distance, which starts small and increases up + * to the GUC-controlled maximum, target_prefetch_pages. This is to + * avoid doing a lot of prefetching in a scan that stops after a few + * tuples because of a LIMIT. */ if (tbm == NULL) { @@ -125,6 +136,15 @@ BitmapHeapNext(BitmapHeapScanState *node) node->tbm = tbm; node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm); node->tbmres = tbmres = NULL; + +#ifdef USE_PREFETCH + if (target_prefetch_pages > 0) + { + node->prefetch_iterator = prefetch_iterator = tbm_begin_iterate(tbm); + node->prefetch_pages = 0; + node->prefetch_target = -1; + } +#endif /* USE_PREFETCH */ } for (;;) @@ -144,6 +164,22 @@ 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 */ + /* * Ignore any claimed entries past what we think is the end of the * relation. (This is probably not necessary given that we got at @@ -165,6 +201,23 @@ BitmapHeapNext(BitmapHeapScanState *node) * Set rs_cindex to first slot to examine */ 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 >= target_prefetch_pages) + /* don't increase any further */ ; + else if (node->prefetch_target >= target_prefetch_pages / 2) + node->prefetch_target = target_prefetch_pages; + else if (node->prefetch_target > 0) + node->prefetch_target *= 2; + else + node->prefetch_target++; +#endif /* USE_PREFETCH */ } else { @@ -172,7 +225,40 @@ BitmapHeapNext(BitmapHeapScanState *node) * Continuing in previously obtained page; advance rs_cindex */ scan->rs_cindex++; + +#ifdef USE_PREFETCH + /* + * Try to prefetch at least a few pages even before we get to the + * second page if we don't stop reading after the first tuple. + */ + if (node->prefetch_target < target_prefetch_pages) + node->prefetch_target++; +#endif /* USE_PREFETCH */ + } + +#ifdef USE_PREFETCH + /* + * We issue prefetch requests *after* fetching the current page + * to try to avoid having prefetching interfere with the main I/O. + */ + 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 */ /* * Out of range? If so, nothing more to look at on this page @@ -379,11 +465,14 @@ ExecBitmapHeapReScan(BitmapHeapScanState *node, ExprContext *exprCtxt) if (node->tbmiterator) tbm_end_iterate(node->tbmiterator); + if (node->prefetch_iterator) + tbm_end_iterate(node->prefetch_iterator); if (node->tbm) tbm_free(node->tbm); node->tbm = NULL; node->tbmiterator = NULL; node->tbmres = NULL; + node->prefetch_iterator = NULL; /* * Always rescan the input immediately, to ensure we can pass down any @@ -429,6 +518,8 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node) */ if (node->tbmiterator) tbm_end_iterate(node->tbmiterator); + if (node->prefetch_iterator) + tbm_end_iterate(node->prefetch_iterator); if (node->tbm) tbm_free(node->tbm); @@ -474,6 +565,9 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags) scanstate->tbm = NULL; scanstate->tbmiterator = NULL; scanstate->tbmres = NULL; + scanstate->prefetch_iterator = NULL; + scanstate->prefetch_pages = 0; + scanstate->prefetch_target = 0; /* * Miscellaneous initialization |