Skip to content

Commit 3971efd

Browse files
MMeenttristan957
authored andcommitted
Prefetch cleanup: (#246)
- Prefetch the pages in index vacuum's sequential scans Implemented in NBTREE, GIST and SP-GIST. BRIN does not have a 2nd phase of vacuum, and both GIN and HASH clean up their indexes in a non-seqscan fashion: GIN scans the btree from left to right, and HASH only scans the initial buckets sequentially.
1 parent f321428 commit 3971efd

File tree

6 files changed

+94
-10
lines changed

6 files changed

+94
-10
lines changed

contrib/pg_prewarm/pg_prewarm.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,8 @@ pg_prewarm(PG_FUNCTION_ARGS)
198198
for (block = first_block; block <= last_block; ++block)
199199
{
200200
Buffer buf;
201-
int prefetch_stop = block + Min(last_block - block + 1, io_concurrency);
201+
BlockNumber prefetch_stop = block + Min(last_block - block + 1,
202+
io_concurrency);
202203
CHECK_FOR_INTERRUPTS();
203204
while (prefetch_block < prefetch_stop)
204205
{

src/backend/access/gist/gistvacuum.c

+20
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "storage/indexfsm.h"
2424
#include "storage/lmgr.h"
2525
#include "utils/memutils.h"
26+
#include "utils/spccache.h"
2627

2728
/* Working state needed by gistbulkdelete */
2829
typedef struct
@@ -130,8 +131,14 @@ gistvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
130131
BlockNumber num_pages;
131132
bool needLock;
132133
BlockNumber blkno;
134+
BlockNumber prefetch_blkno;
135+
int io_concurrency;
133136
MemoryContext oldctx;
134137

138+
io_concurrency = get_tablespace_maintenance_io_concurrency(
139+
rel->rd_rel->reltablespace
140+
);
141+
135142
/*
136143
* Reset fields that track information about the entire index now. This
137144
* avoids double-counting in the case where a single VACUUM command
@@ -209,6 +216,7 @@ gistvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
209216
needLock = !RELATION_IS_LOCAL(rel);
210217

211218
blkno = GIST_ROOT_BLKNO;
219+
prefetch_blkno = blkno;
212220
for (;;)
213221
{
214222
/* Get the current relation length */
@@ -221,9 +229,21 @@ gistvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
221229
/* Quit if we've scanned the whole relation */
222230
if (blkno >= num_pages)
223231
break;
232+
233+
if (prefetch_blkno < blkno)
234+
prefetch_blkno = blkno;
235+
for (; prefetch_blkno < num_pages &&
236+
prefetch_blkno < blkno + io_concurrency; prefetch_blkno++)
237+
PrefetchBuffer(rel, MAIN_FORKNUM, prefetch_blkno);
238+
224239
/* Iterate over pages, then loop back to recheck length */
225240
for (; blkno < num_pages; blkno++)
241+
{
242+
if (io_concurrency > 0 && prefetch_blkno < num_pages)
243+
PrefetchBuffer(rel, MAIN_FORKNUM, prefetch_blkno++);
244+
226245
gistvacuumpage(&vstate, blkno, blkno);
246+
}
227247
}
228248

229249
/*

src/backend/access/hash/hash.c

+16
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "utils/builtins.h"
3333
#include "utils/index_selfuncs.h"
3434
#include "utils/rel.h"
35+
#include "utils/spccache.h"
3536

3637
/* Working state for hashbuild and its callback */
3738
typedef struct
@@ -466,13 +467,17 @@ hashbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
466467
Bucket orig_maxbucket;
467468
Bucket cur_maxbucket;
468469
Bucket cur_bucket;
470+
Bucket prf_bucket;
469471
Buffer metabuf = InvalidBuffer;
470472
HashMetaPage metap;
471473
HashMetaPage cachedmetap;
474+
int io_concurrency;
472475

473476
tuples_removed = 0;
474477
num_index_tuples = 0;
475478

479+
io_concurrency = get_tablespace_maintenance_io_concurrency(rel->rd_rel->reltablespace);
480+
476481
/*
477482
* We need a copy of the metapage so that we can use its hashm_spares[]
478483
* values to compute bucket page addresses, but a cached copy should be
@@ -487,9 +492,14 @@ hashbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
487492

488493
/* Scan the buckets that we know exist */
489494
cur_bucket = 0;
495+
prf_bucket = cur_bucket;
490496
cur_maxbucket = orig_maxbucket;
491497

492498
loop_top:
499+
for (; prf_bucket <= cur_maxbucket &&
500+
prf_bucket < cur_bucket + io_concurrency; prf_bucket++)
501+
PrefetchBuffer(rel, MAIN_FORKNUM, BUCKET_TO_BLKNO(cachedmetap, prf_bucket));
502+
493503
while (cur_bucket <= cur_maxbucket)
494504
{
495505
BlockNumber bucket_blkno;
@@ -500,6 +510,12 @@ hashbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
500510
Page page;
501511
bool split_cleanup = false;
502512

513+
if (io_concurrency > 0 && prf_bucket <= cur_maxbucket)
514+
{
515+
PrefetchBuffer(rel, MAIN_FORKNUM, BUCKET_TO_BLKNO(cachedmetap, prf_bucket));
516+
prf_bucket++;
517+
}
518+
503519
/* Get address of bucket's start page */
504520
bucket_blkno = BUCKET_TO_BLKNO(cachedmetap, cur_bucket);
505521

src/backend/access/heap/vacuumlazy.c

+17-8
Original file line numberDiff line numberDiff line change
@@ -981,7 +981,8 @@ lazy_scan_heap(LVRelState *vacrel)
981981
*/
982982
visibilitymap_pin(vacrel->rel, blkno, &vmbuffer);
983983

984-
if (vacrel->io_concurrency > 0) {
984+
if (vacrel->io_concurrency > 0)
985+
{
985986
/*
986987
* Prefetch io_concurrency blocks ahead
987988
*/
@@ -2464,32 +2465,40 @@ lazy_vacuum_heap_rel(LVRelState *vacrel)
24642465

24652466
tblk = ItemPointerGetBlockNumber(&vacrel->dead_items->items[index]);
24662467

2467-
if (vacrel->io_concurrency > 0) {
2468+
if (vacrel->io_concurrency > 0)
2469+
{
24682470
/*
24692471
* If we're just starting out, prefetch N consecutive blocks.
24702472
* If not, only the next 1 block
24712473
*/
2472-
if (pindex == 0) {
2474+
if (pindex == 0)
2475+
{
24732476
int prefetch_budget = Min(vacrel->dead_items->num_items,
24742477
Min(vacrel->rel_pages,
24752478
vacrel->io_concurrency));
24762479
BlockNumber prev_prefetch = ItemPointerGetBlockNumber(&vacrel->dead_items->items[pindex]);
24772480
PrefetchBuffer(vacrel->rel, MAIN_FORKNUM, prev_prefetch);
24782481

24792482
while (++pindex < vacrel->dead_items->num_items &&
2480-
prefetch_budget > 0) {
2483+
prefetch_budget > 0)
2484+
{
24812485
ItemPointer ptr = &vacrel->dead_items->items[pindex];
2482-
if (ItemPointerGetBlockNumber(ptr) != prev_prefetch) {
2486+
if (ItemPointerGetBlockNumber(ptr) != prev_prefetch)
2487+
{
24832488
prev_prefetch = ItemPointerGetBlockNumber(ptr);
24842489
prefetch_budget -= 1;
24852490
PrefetchBuffer(vacrel->rel, MAIN_FORKNUM, prev_prefetch);
24862491
}
24872492
}
2488-
} else if (pindex < vacrel->dead_items->num_items) {
2493+
}
2494+
else if (pindex < vacrel->dead_items->num_items)
2495+
{
24892496
BlockNumber previous = ItemPointerGetBlockNumber(&vacrel->dead_items->items[pindex]);
2490-
while (++pindex < vacrel->dead_items->num_items) {
2497+
while (++pindex < vacrel->dead_items->num_items)
2498+
{
24912499
BlockNumber toPrefetch = ItemPointerGetBlockNumber(&vacrel->dead_items->items[pindex]);
2492-
if (previous != toPrefetch) {
2500+
if (previous != toPrefetch)
2501+
{
24932502
PrefetchBuffer(vacrel->rel, MAIN_FORKNUM, toPrefetch);
24942503
break;
24952504
}

src/backend/access/nbtree/nbtree.c

+18
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "utils/builtins.h"
3838
#include "utils/index_selfuncs.h"
3939
#include "utils/memutils.h"
40+
#include "utils/spccache.h"
4041

4142

4243
/*
@@ -909,6 +910,8 @@ btvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
909910
BTVacState vstate;
910911
BlockNumber num_pages;
911912
BlockNumber scanblkno;
913+
BlockNumber prefetch_blkno;
914+
int io_concurrency;
912915
bool needLock;
913916

914917
/*
@@ -948,6 +951,9 @@ btvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
948951
vstate.maxbufsize = 0;
949952
vstate.pendingpages = NULL;
950953
vstate.npendingpages = 0;
954+
955+
io_concurrency = get_tablespace_maintenance_io_concurrency(rel->rd_rel->reltablespace);
956+
951957
/* Consider applying _bt_pendingfsm_finalize optimization */
952958
_bt_pendingfsm_init(rel, &vstate, (callback == NULL));
953959

@@ -976,6 +982,8 @@ btvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
976982
needLock = !RELATION_IS_LOCAL(rel);
977983

978984
scanblkno = BTREE_METAPAGE + 1;
985+
prefetch_blkno = scanblkno;
986+
979987
for (;;)
980988
{
981989
/* Get the current relation length */
@@ -992,9 +1000,19 @@ btvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
9921000
/* Quit if we've scanned the whole relation */
9931001
if (scanblkno >= num_pages)
9941002
break;
1003+
1004+
if (prefetch_blkno < scanblkno)
1005+
prefetch_blkno = scanblkno;
1006+
for (; prefetch_blkno < num_pages &&
1007+
prefetch_blkno < scanblkno + io_concurrency; prefetch_blkno++)
1008+
PrefetchBuffer(rel, MAIN_FORKNUM, prefetch_blkno);
1009+
9951010
/* Iterate over pages, then loop back to recheck length */
9961011
for (; scanblkno < num_pages; scanblkno++)
9971012
{
1013+
if (io_concurrency > 0 && prefetch_blkno < num_pages)
1014+
PrefetchBuffer(rel, MAIN_FORKNUM, prefetch_blkno++);
1015+
9981016
btvacuumpage(&vstate, scanblkno);
9991017
if (info->report_progress)
10001018
pgstat_progress_update_param(PROGRESS_SCAN_BLOCKS_DONE,

src/backend/access/spgist/spgvacuum.c

+21-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "storage/indexfsm.h"
2828
#include "storage/lmgr.h"
2929
#include "utils/snapmgr.h"
30+
#include "utils/spccache.h"
3031

3132

3233
/* Entry in pending-list of TIDs we need to revisit */
@@ -796,7 +797,14 @@ spgvacuumscan(spgBulkDeleteState *bds)
796797
Relation index = bds->info->index;
797798
bool needLock;
798799
BlockNumber num_pages,
799-
blkno;
800+
blkno,
801+
prefetch_blkno;
802+
int io_concurrency;
803+
804+
/* initiate concurrency */
805+
io_concurrency = get_tablespace_maintenance_io_concurrency(
806+
index->rd_rel->reltablespace
807+
);
800808

801809
/* Finish setting up spgBulkDeleteState */
802810
initSpGistState(&bds->spgstate, index);
@@ -824,6 +832,8 @@ spgvacuumscan(spgBulkDeleteState *bds)
824832
* in btvacuumscan().
825833
*/
826834
blkno = SPGIST_METAPAGE_BLKNO + 1;
835+
prefetch_blkno = blkno;
836+
827837
for (;;)
828838
{
829839
/* Get the current relation length */
@@ -836,9 +846,19 @@ spgvacuumscan(spgBulkDeleteState *bds)
836846
/* Quit if we've scanned the whole relation */
837847
if (blkno >= num_pages)
838848
break;
849+
850+
if (prefetch_blkno < blkno)
851+
prefetch_blkno = blkno;
852+
for (; prefetch_blkno < num_pages &&
853+
prefetch_blkno < blkno + io_concurrency; prefetch_blkno++)
854+
PrefetchBuffer(index, MAIN_FORKNUM, prefetch_blkno);
855+
839856
/* Iterate over pages, then loop back to recheck length */
840857
for (; blkno < num_pages; blkno++)
841858
{
859+
if (io_concurrency > 0 && prefetch_blkno < num_pages)
860+
PrefetchBuffer(index, MAIN_FORKNUM, prefetch_blkno++);
861+
842862
spgvacuumpage(bds, blkno);
843863
/* empty the pending-list after each page */
844864
if (bds->pendingList != NULL)

0 commit comments

Comments
 (0)