Skip to content

Commit e215166

Browse files
Use streaming read I/O in SP-GiST vacuuming
Like 69273b8 did for GiST vacuuming, make SP-GiST vacuum use the read stream API for vacuuming physically contiguous index pages. Concurrent insertions may cause SP-GiST index tuples to be redirected. While vacuuming, these are added to a pending list which is later processed to ensure no dead tuples are left behind. Pages containing such tuples are still read by directly calling ReadBuffer() and do not use the read stream API. Author: Andrey M. Borodin <x4mmm@yandex-team.ru> Reviewed-by: Melanie Plageman <melanieplageman@gmail.com> Discussion: https://postgr.es/m/37432403-8657-403B-9CDF-5A642BECDD81%40yandex-team.ru
1 parent e51ca40 commit e215166

File tree

1 file changed

+42
-13
lines changed

1 file changed

+42
-13
lines changed

src/backend/access/spgist/spgvacuum.c

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "storage/bufmgr.h"
2626
#include "storage/indexfsm.h"
2727
#include "storage/lmgr.h"
28+
#include "storage/read_stream.h"
2829
#include "utils/snapmgr.h"
2930

3031

@@ -618,17 +619,12 @@ vacuumRedirectAndPlaceholder(Relation index, Relation heaprel, Buffer buffer)
618619
* Process one page during a bulkdelete scan
619620
*/
620621
static void
621-
spgvacuumpage(spgBulkDeleteState *bds, BlockNumber blkno)
622+
spgvacuumpage(spgBulkDeleteState *bds, Buffer buffer)
622623
{
623624
Relation index = bds->info->index;
624-
Buffer buffer;
625+
BlockNumber blkno = BufferGetBlockNumber(buffer);
625626
Page page;
626627

627-
/* call vacuum_delay_point while not holding any buffer lock */
628-
vacuum_delay_point(false);
629-
630-
buffer = ReadBufferExtended(index, MAIN_FORKNUM, blkno,
631-
RBM_NORMAL, bds->info->strategy);
632628
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
633629
page = (Page) BufferGetPage(buffer);
634630

@@ -805,8 +801,9 @@ spgvacuumscan(spgBulkDeleteState *bds)
805801
{
806802
Relation index = bds->info->index;
807803
bool needLock;
808-
BlockNumber num_pages,
809-
blkno;
804+
BlockNumber num_pages;
805+
BlockRangeReadStreamPrivate p;
806+
ReadStream *stream = NULL;
810807

811808
/* Finish setting up spgBulkDeleteState */
812809
initSpGistState(&bds->spgstate, index);
@@ -824,6 +821,14 @@ spgvacuumscan(spgBulkDeleteState *bds)
824821

825822
/* We can skip locking for new or temp relations */
826823
needLock = !RELATION_IS_LOCAL(index);
824+
p.current_blocknum = SPGIST_METAPAGE_BLKNO + 1;
825+
stream = read_stream_begin_relation(READ_STREAM_FULL,
826+
bds->info->strategy,
827+
index,
828+
MAIN_FORKNUM,
829+
block_range_read_stream_cb,
830+
&p,
831+
0);
827832

828833
/*
829834
* The outer loop iterates over all index pages except the metapage, in
@@ -833,7 +838,6 @@ spgvacuumscan(spgBulkDeleteState *bds)
833838
* delete some deletable tuples. See more extensive comments about this
834839
* in btvacuumscan().
835840
*/
836-
blkno = SPGIST_METAPAGE_BLKNO + 1;
837841
for (;;)
838842
{
839843
/* Get the current relation length */
@@ -844,18 +848,43 @@ spgvacuumscan(spgBulkDeleteState *bds)
844848
UnlockRelationForExtension(index, ExclusiveLock);
845849

846850
/* Quit if we've scanned the whole relation */
847-
if (blkno >= num_pages)
851+
if (p.current_blocknum >= num_pages)
848852
break;
853+
854+
p.last_exclusive = num_pages;
855+
849856
/* Iterate over pages, then loop back to recheck length */
850-
for (; blkno < num_pages; blkno++)
857+
while (true)
851858
{
852-
spgvacuumpage(bds, blkno);
859+
Buffer buf;
860+
861+
/* call vacuum_delay_point while not holding any buffer lock */
862+
vacuum_delay_point(false);
863+
864+
buf = read_stream_next_buffer(stream, NULL);
865+
866+
if (!BufferIsValid(buf))
867+
break;
868+
869+
spgvacuumpage(bds, buf);
870+
853871
/* empty the pending-list after each page */
854872
if (bds->pendingList != NULL)
855873
spgprocesspending(bds);
856874
}
875+
876+
Assert(read_stream_next_buffer(stream, NULL) == InvalidBuffer);
877+
878+
/*
879+
* We have to reset the read stream to use it again. After returning
880+
* InvalidBuffer, the read stream API won't invoke our callback again
881+
* until the stream has been reset.
882+
*/
883+
read_stream_reset(stream);
857884
}
858885

886+
read_stream_end(stream);
887+
859888
/* Propagate local lastUsedPages cache to metablock */
860889
SpGistUpdateMetaPage(index);
861890

0 commit comments

Comments
 (0)