Skip to content

Commit 87c5bb6

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 f34afc9 commit 87c5bb6

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
@@ -973,12 +973,27 @@ lazy_scan_heap(LVRelState *vacrel)
973973
*/
974974
visibilitymap_pin(vacrel->rel, blkno, &vmbuffer);
975975

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

984999
/* Finished preparatory checks. Actually scan the page. */
@@ -2404,7 +2419,8 @@ lazy_vacuum_all_indexes(LVRelState *vacrel)
24042419
static void
24052420
lazy_vacuum_heap_rel(LVRelState *vacrel)
24062421
{
2407-
int index;
2422+
int index,
2423+
pindex;
24082424
BlockNumber vacuumed_pages;
24092425
Buffer vmbuffer = InvalidBuffer;
24102426
LVSavedErrInfo saved_err_info;
@@ -2425,6 +2441,7 @@ lazy_vacuum_heap_rel(LVRelState *vacrel)
24252441
vacuumed_pages = 0;
24262442

24272443
index = 0;
2444+
pindex = 0;
24282445
while (index < vacrel->dead_items->num_items)
24292446
{
24302447
BlockNumber tblk;
@@ -2435,13 +2452,44 @@ lazy_vacuum_heap_rel(LVRelState *vacrel)
24352452
vacuum_delay_point();
24362453

24372454
tblk = ItemPointerGetBlockNumber(&vacrel->dead_items->items[index]);
2438-
if (enable_seqscan_prefetch)
2455+
2456+
if (enable_seqscan_prefetch && seqscan_prefetch_buffers > 0)
24392457
{
2440-
int prefetch_limit = Min(vacrel->dead_items->num_items - index - 1, seqscan_prefetch_buffers);
2441-
smgr_reset_prefetch(RelationGetSmgr(vacrel->rel));
2442-
for (int i = 1; i <= prefetch_limit; i++)
2443-
PrefetchBuffer(vacrel->rel, MAIN_FORKNUM, ItemPointerGetBlockNumber(&vacrel->dead_items->items[index + i]));
2458+
/*
2459+
* If we're just starting out, prefetch N consecutive blocks.
2460+
* If not, only the next 1 block
2461+
*/
2462+
if (index == 0)
2463+
{
2464+
int prefetch_limit = Min(vacrel->dead_items->num_items - 1,
2465+
Min(vacrel->rel_pages,
2466+
seqscan_prefetch_buffers));
2467+
BlockNumber prev_prefetch = 0;
2468+
2469+
while (++pindex < vacrel->dead_items->num_items &&
2470+
prefetch_limit > 0)
2471+
{
2472+
ItemPointer ptr = &vacrel->dead_items->items[pindex];
2473+
if (ItemPointerGetBlockNumber(ptr) != prev_prefetch)
2474+
{
2475+
prev_prefetch = ItemPointerGetBlockNumber(ptr);
2476+
prefetch_limit -= 1;
2477+
PrefetchBuffer(vacrel->rel, MAIN_FORKNUM, prev_prefetch);
2478+
}
2479+
}
2480+
}
2481+
else
2482+
{
2483+
BlockNumber toPrefetch = ItemPointerGetBlockNumber(&vacrel->dead_items->items[pindex]);
2484+
while (pindex < vacrel->dead_items->num_items)
2485+
{
2486+
if (toPrefetch != ItemPointerGetBlockNumber(&vacrel->dead_items->items[pindex]))
2487+
break;
2488+
}
2489+
PrefetchBuffer(vacrel->rel, MAIN_FORKNUM, toPrefetch);
2490+
}
24442491
}
2492+
24452493
vacrel->blkno = tblk;
24462494
buf = ReadBufferExtended(vacrel->rel, MAIN_FORKNUM, tblk, RBM_NORMAL,
24472495
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,
@@ -532,15 +531,6 @@ smgrprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
532531
return (*reln->smgr).smgr_prefetch(reln, forknum, blocknum);
533532
}
534533

535-
/*
536-
* smgr_reset_prefetch() -- Cancel all previos prefetch requests
537-
*/
538-
void
539-
smgr_reset_prefetch(SMgrRelation reln)
540-
{
541-
(*reln->smgr).smgr_reset_prefetch(reln);
542-
}
543-
544534
/*
545535
* smgrread() -- read a particular block from a relation into the supplied
546536
* 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)