Skip to content

Commit 2081680

Browse files
MMeenttristan957
authored andcommitted
Optimize prefetch patterns in both heap seqscan and vacuum scans. (#228)
Previously, we called PrefetchBuffer [NBlkScanned * seqscan_prefetch_buffers] times in each of those situations, but now only NBlkScanned. In addition, the prefetch mechanism for the vacuum scans is now based on blocks instead of tuples - improving the efficiency.
1 parent c912d88 commit 2081680

File tree

4 files changed

+79
-29
lines changed

4 files changed

+79
-29
lines changed

src/backend/access/heap/heapam.c

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -399,19 +399,32 @@ heapgetpage(TableScanDesc sscan, BlockNumber page)
399399
*/
400400
CHECK_FOR_INTERRUPTS();
401401

402-
/* Prefetch next block */
403-
if (enable_seqscan_prefetch)
402+
/* Prefetch up to seqscan_prefetch_buffers blocks ahead */
403+
if (enable_seqscan_prefetch && seqscan_prefetch_buffers > 0)
404404
{
405-
int prefetch_limit = seqscan_prefetch_buffers;
405+
uint32 prefetch_limit = seqscan_prefetch_buffers;
406+
BlockNumber prefetch_start = page;
406407
ParallelBlockTableScanWorker pbscanwork = scan->rs_parallelworkerdata;
408+
407409
if (pbscanwork != NULL && pbscanwork->phsw_chunk_remaining < prefetch_limit)
408410
prefetch_limit = pbscanwork->phsw_chunk_remaining;
409-
if (page + prefetch_limit >= scan->rs_nblocks)
410-
prefetch_limit = scan->rs_nblocks - page - 1;
411411

412-
smgr_reset_prefetch(RelationGetSmgr(scan->rs_base.rs_rd));
412+
/*
413+
* If this is the first page, initiate prefetch of pages page..page + n.
414+
* On each subsequent call, prefetch the next page that we haven't
415+
* prefetched yet, at page + n.
416+
*/
417+
if (scan->rs_startblock != page)
418+
{
419+
prefetch_start = (page + prefetch_limit - 1) % scan->rs_nblocks;
420+
prefetch_limit = 1;
421+
}
422+
else
423+
prefetch_start = page;
424+
413425
for (int i = 1; i <= prefetch_limit; i++)
414-
PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM, page+i);
426+
PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM,
427+
(prefetch_start+i) % scan->rs_nblocks);
415428
}
416429

417430
/* read page using selected strategy */

src/backend/access/heap/vacuumlazy.c

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -971,12 +971,27 @@ lazy_scan_heap(LVRelState *vacrel)
971971
*/
972972
visibilitymap_pin(vacrel->rel, blkno, &vmbuffer);
973973

974-
if (enable_seqscan_prefetch)
974+
if (enable_seqscan_prefetch && seqscan_prefetch_buffers > 0)
975975
{
976-
int prefetch_limit = Min(rel_pages - blkno - 1, seqscan_prefetch_buffers);
977-
smgr_reset_prefetch(RelationGetSmgr(vacrel->rel));
978-
for (int i = 1; i <= prefetch_limit; i++)
979-
PrefetchBuffer(vacrel->rel, MAIN_FORKNUM, blkno+i);
976+
/*
977+
* If we're starting the scan, we need to prefetch the first N pages.
978+
* If not, we need to only prefetch page blkno+n.
979+
*/
980+
if (blkno == 0)
981+
{
982+
int prefetch_limit = Min(rel_pages - blkno - 1,
983+
seqscan_prefetch_buffers);
984+
985+
for (int i = 1; i <= prefetch_limit; i++)
986+
PrefetchBuffer(vacrel->rel, MAIN_FORKNUM, blkno+i);
987+
}
988+
else
989+
{
990+
/* No need to prefetch past the end of the relation */
991+
if (blkno + seqscan_prefetch_buffers < rel_pages)
992+
PrefetchBuffer(vacrel->rel, MAIN_FORKNUM,
993+
blkno + seqscan_prefetch_buffers);
994+
}
980995
}
981996

982997
/* Finished preparatory checks. Actually scan the page. */
@@ -2402,7 +2417,8 @@ lazy_vacuum_all_indexes(LVRelState *vacrel)
24022417
static void
24032418
lazy_vacuum_heap_rel(LVRelState *vacrel)
24042419
{
2405-
int index;
2420+
int index,
2421+
pindex;
24062422
BlockNumber vacuumed_pages;
24072423
Buffer vmbuffer = InvalidBuffer;
24082424
LVSavedErrInfo saved_err_info;
@@ -2423,6 +2439,7 @@ lazy_vacuum_heap_rel(LVRelState *vacrel)
24232439
vacuumed_pages = 0;
24242440

24252441
index = 0;
2442+
pindex = 0;
24262443
while (index < vacrel->dead_items->num_items)
24272444
{
24282445
BlockNumber tblk;
@@ -2433,13 +2450,44 @@ lazy_vacuum_heap_rel(LVRelState *vacrel)
24332450
vacuum_delay_point();
24342451

24352452
tblk = ItemPointerGetBlockNumber(&vacrel->dead_items->items[index]);
2436-
if (enable_seqscan_prefetch)
2453+
2454+
if (enable_seqscan_prefetch && seqscan_prefetch_buffers > 0)
24372455
{
2438-
int prefetch_limit = Min(vacrel->dead_items->num_items - index - 1, seqscan_prefetch_buffers);
2439-
smgr_reset_prefetch(RelationGetSmgr(vacrel->rel));
2440-
for (int i = 1; i <= prefetch_limit; i++)
2441-
PrefetchBuffer(vacrel->rel, MAIN_FORKNUM, ItemPointerGetBlockNumber(&vacrel->dead_items->items[index + i]));
2456+
/*
2457+
* If we're just starting out, prefetch N consecutive blocks.
2458+
* If not, only the next 1 block
2459+
*/
2460+
if (index == 0)
2461+
{
2462+
int prefetch_limit = Min(vacrel->dead_items->num_items - 1,
2463+
Min(vacrel->rel_pages,
2464+
seqscan_prefetch_buffers));
2465+
BlockNumber prev_prefetch = 0;
2466+
2467+
while (++pindex < vacrel->dead_items->num_items &&
2468+
prefetch_limit > 0)
2469+
{
2470+
ItemPointer ptr = &vacrel->dead_items->items[pindex];
2471+
if (ItemPointerGetBlockNumber(ptr) != prev_prefetch)
2472+
{
2473+
prev_prefetch = ItemPointerGetBlockNumber(ptr);
2474+
prefetch_limit -= 1;
2475+
PrefetchBuffer(vacrel->rel, MAIN_FORKNUM, prev_prefetch);
2476+
}
2477+
}
2478+
}
2479+
else
2480+
{
2481+
BlockNumber toPrefetch = ItemPointerGetBlockNumber(&vacrel->dead_items->items[pindex]);
2482+
while (pindex < vacrel->dead_items->num_items)
2483+
{
2484+
if (toPrefetch != ItemPointerGetBlockNumber(&vacrel->dead_items->items[pindex]))
2485+
break;
2486+
}
2487+
PrefetchBuffer(vacrel->rel, MAIN_FORKNUM, toPrefetch);
2488+
}
24422489
}
2490+
24432491
vacrel->blkno = tblk;
24442492
buf = ReadBufferExtended(vacrel->rel, MAIN_FORKNUM, tblk, RBM_NORMAL,
24452493
vacrel->bstrategy);

src/backend/storage/smgr/smgr.c

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ static const f_smgr smgr_md = {
3838
.smgr_unlink = mdunlink,
3939
.smgr_extend = mdextend,
4040
.smgr_prefetch = mdprefetch,
41-
.smgr_reset_prefetch = md_reset_prefetch,
4241
.smgr_read = mdread,
4342
.smgr_write = mdwrite,
4443
.smgr_writeback = mdwriteback,
@@ -533,15 +532,6 @@ smgrprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
533532
return (*reln->smgr).smgr_prefetch(reln, forknum, blocknum);
534533
}
535534

536-
/*
537-
* smgr_reset_prefetch() -- Cancel all previos prefetch requests
538-
*/
539-
void
540-
smgr_reset_prefetch(SMgrRelation reln)
541-
{
542-
(*reln->smgr).smgr_reset_prefetch(reln);
543-
}
544-
545535
/*
546536
* smgrread() -- read a particular block from a relation into the supplied
547537
* buffer.

src/include/storage/smgr.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,6 @@ extern void smgrextend(SMgrRelation reln, ForkNumber forknum,
159159
BlockNumber blocknum, char *buffer, bool skipFsync);
160160
extern bool smgrprefetch(SMgrRelation reln, ForkNumber forknum,
161161
BlockNumber blocknum);
162-
extern void smgr_reset_prefetch(SMgrRelation reln);
163162
extern void smgrread(SMgrRelation reln, ForkNumber forknum,
164163
BlockNumber blocknum, char *buffer);
165164
extern void smgrwrite(SMgrRelation reln, ForkNumber forknum,

0 commit comments

Comments
 (0)