From f9f4ecc74d91dd5ea613ed461280a49811820458 Mon Sep 17 00:00:00 2001 From: reshke Date: Thu, 23 Oct 2025 17:53:30 +0000 Subject: [PATCH v2] Use log_newpage_range in HASH index build --- src/backend/access/hash/hash.c | 25 ++++++++++++++-------- src/backend/access/hash/hashinsert.c | 8 +++---- src/backend/access/hash/hashovfl.c | 19 +++++++++-------- src/backend/access/hash/hashpage.c | 32 ++++++++++++++++------------ src/backend/access/hash/hashsort.c | 4 +++- src/include/access/hash.h | 14 ++++++------ 6 files changed, 58 insertions(+), 44 deletions(-) diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c index 53061c819fb..4fff0634e6d 100644 --- a/src/backend/access/hash/hash.c +++ b/src/backend/access/hash/hash.c @@ -141,7 +141,7 @@ hashbuild(Relation heap, Relation index, IndexInfo *indexInfo) estimate_rel_size(heap, NULL, &relpages, &reltuples, &allvisfrac); /* Initialize the hash index metadata page and initial buckets */ - num_buckets = _hash_init(index, reltuples, MAIN_FORKNUM); + num_buckets = _hash_init(index, reltuples, MAIN_FORKNUM, true); /* * If we just insert the tuples into the index in scan order, then @@ -190,6 +190,11 @@ hashbuild(Relation heap, Relation index, IndexInfo *indexInfo) _h_spooldestroy(buildstate.spool); } + if (RelationNeedsWAL(index)) + log_newpage_range(index, MAIN_FORKNUM, + 0, RelationGetNumberOfBlocks(index), + true); + /* * Return statistics */ @@ -207,7 +212,7 @@ hashbuild(Relation heap, Relation index, IndexInfo *indexInfo) void hashbuildempty(Relation index) { - _hash_init(index, 0, INIT_FORKNUM); + _hash_init(index, 0, INIT_FORKNUM, false); } /* @@ -241,7 +246,7 @@ hashbuildCallback(Relation index, itup = index_form_tuple(RelationGetDescr(index), index_values, index_isnull); itup->t_tid = *tid; - _hash_doinsert(index, itup, buildstate->heapRel, false); + _hash_doinsert(index, itup, buildstate->heapRel, false, true); pfree(itup); } @@ -275,7 +280,7 @@ hashinsert(Relation rel, Datum *values, bool *isnull, itup = index_form_tuple(RelationGetDescr(rel), index_values, index_isnull); itup->t_tid = *ht_ctid; - _hash_doinsert(rel, itup, heapRel, false); + _hash_doinsert(rel, itup, heapRel, false, false); pfree(itup); @@ -556,7 +561,7 @@ loop_top: cachedmetap->hashm_highmask, cachedmetap->hashm_lowmask, &tuples_removed, &num_index_tuples, split_cleanup, - callback, callback_state); + callback, callback_state, false); _hash_dropbuf(rel, bucket_buf); @@ -692,7 +697,8 @@ hashbucketcleanup(Relation rel, Bucket cur_bucket, Buffer bucket_buf, uint32 maxbucket, uint32 highmask, uint32 lowmask, double *tuples_removed, double *num_index_tuples, bool split_cleanup, - IndexBulkDeleteCallback callback, void *callback_state) + IndexBulkDeleteCallback callback, void *callback_state, + bool isbuild) { BlockNumber blkno; Buffer buf; @@ -719,6 +725,7 @@ hashbucketcleanup(Relation rel, Bucket cur_bucket, Buffer bucket_buf, bool retain_pin = false; bool clear_dead_marking = false; + /* XXX: what if isbuild = true ? */ vacuum_delay_point(false); page = BufferGetPage(buf); @@ -817,7 +824,7 @@ hashbucketcleanup(Relation rel, Bucket cur_bucket, Buffer bucket_buf, MarkBufferDirty(buf); /* XLOG stuff */ - if (RelationNeedsWAL(rel)) + if (RelationNeedsWAL(rel) && !isbuild) { xl_hash_delete xlrec; XLogRecPtr recptr; @@ -903,7 +910,7 @@ hashbucketcleanup(Relation rel, Bucket cur_bucket, Buffer bucket_buf, MarkBufferDirty(bucket_buf); /* XLOG stuff */ - if (RelationNeedsWAL(rel)) + if (RelationNeedsWAL(rel) && !isbuild) { XLogRecPtr recptr; @@ -924,7 +931,7 @@ hashbucketcleanup(Relation rel, Bucket cur_bucket, Buffer bucket_buf, */ if (bucket_dirty && IsBufferCleanupOK(bucket_buf)) _hash_squeezebucket(rel, cur_bucket, bucket_blkno, bucket_buf, - bstrategy); + bstrategy, isbuild); else LockBuffer(bucket_buf, BUFFER_LOCK_UNLOCK); } diff --git a/src/backend/access/hash/hashinsert.c b/src/backend/access/hash/hashinsert.c index 10de1580dc2..3692cebb0ac 100644 --- a/src/backend/access/hash/hashinsert.c +++ b/src/backend/access/hash/hashinsert.c @@ -35,7 +35,7 @@ static void _hash_vacuum_one_page(Relation rel, Relation hrel, * order. */ void -_hash_doinsert(Relation rel, IndexTuple itup, Relation heapRel, bool sorted) +_hash_doinsert(Relation rel, IndexTuple itup, Relation heapRel, bool sorted, bool isbuild) { Buffer buf = InvalidBuffer; Buffer bucket_buf; @@ -178,7 +178,7 @@ restart_insert: LockBuffer(buf, BUFFER_LOCK_UNLOCK); /* chain to a new overflow page */ - buf = _hash_addovflpage(rel, metabuf, buf, (buf == bucket_buf)); + buf = _hash_addovflpage(rel, metabuf, buf, (buf == bucket_buf), isbuild); page = BufferGetPage(buf); /* should fit now, given test above */ @@ -213,7 +213,7 @@ restart_insert: MarkBufferDirty(metabuf); /* XLOG stuff */ - if (RelationNeedsWAL(rel)) + if (RelationNeedsWAL(rel) && !isbuild) { xl_hash_insert xlrec; XLogRecPtr recptr; @@ -249,7 +249,7 @@ restart_insert: /* Attempt to split if a split is needed */ if (do_expand) - _hash_expandtable(rel, metabuf); + _hash_expandtable(rel, metabuf, isbuild); /* Finally drop our pin on the metapage */ _hash_dropbuf(rel, metabuf); diff --git a/src/backend/access/hash/hashovfl.c b/src/backend/access/hash/hashovfl.c index 4f5fd3b2837..401447ada3e 100644 --- a/src/backend/access/hash/hashovfl.c +++ b/src/backend/access/hash/hashovfl.c @@ -109,7 +109,7 @@ _hash_ovflblkno_to_bitno(HashMetaPage metap, BlockNumber ovflblkno) * pages might have been added to the bucket chain in between. */ Buffer -_hash_addovflpage(Relation rel, Buffer metabuf, Buffer buf, bool retain_pin) +_hash_addovflpage(Relation rel, Buffer metabuf, Buffer buf, bool retain_pin, bool isbuild) { Buffer ovflbuf; Page page; @@ -379,7 +379,7 @@ found: MarkBufferDirty(buf); /* XLOG stuff */ - if (RelationNeedsWAL(rel)) + if (RelationNeedsWAL(rel) && !isbuild) { XLogRecPtr recptr; xl_hash_add_ovfl_page xlrec; @@ -490,7 +490,7 @@ BlockNumber _hash_freeovflpage(Relation rel, Buffer bucketbuf, Buffer ovflbuf, Buffer wbuf, IndexTuple *itups, OffsetNumber *itup_offsets, Size *tups_size, uint16 nitups, - BufferAccessStrategy bstrategy) + BufferAccessStrategy bstrategy, bool isbuild) { HashMetaPage metap; Buffer metabuf; @@ -575,7 +575,7 @@ _hash_freeovflpage(Relation rel, Buffer bucketbuf, Buffer ovflbuf, LockBuffer(metabuf, BUFFER_LOCK_EXCLUSIVE); /* This operation needs to log multiple tuples, prepare WAL for that */ - if (RelationNeedsWAL(rel)) + if (RelationNeedsWAL(rel) && !isbuild) XLogEnsureRecordSpace(HASH_XLOG_FREE_OVFL_BUFS, 4 + nitups); START_CRIT_SECTION(); @@ -642,7 +642,7 @@ _hash_freeovflpage(Relation rel, Buffer bucketbuf, Buffer ovflbuf, } /* XLOG stuff */ - if (RelationNeedsWAL(rel)) + if (RelationNeedsWAL(rel) && !isbuild) { xl_hash_squeeze_page xlrec; XLogRecPtr recptr; @@ -843,7 +843,8 @@ _hash_squeezebucket(Relation rel, Bucket bucket, BlockNumber bucket_blkno, Buffer bucket_buf, - BufferAccessStrategy bstrategy) + BufferAccessStrategy bstrategy, + bool isbuild) { BlockNumber wblkno; BlockNumber rblkno; @@ -965,7 +966,7 @@ readpage: * This operation needs to log multiple tuples, prepare * WAL for that. */ - if (RelationNeedsWAL(rel)) + if (RelationNeedsWAL(rel) && !isbuild) XLogEnsureRecordSpace(0, 3 + nitups); START_CRIT_SECTION(); @@ -984,7 +985,7 @@ readpage: MarkBufferDirty(rbuf); /* XLOG stuff */ - if (RelationNeedsWAL(rel)) + if (RelationNeedsWAL(rel) && !isbuild) { XLogRecPtr recptr; xl_hash_move_page_contents xlrec; @@ -1094,7 +1095,7 @@ readpage: /* free this overflow page (releases rbuf) */ _hash_freeovflpage(rel, bucket_buf, rbuf, wbuf, itups, itup_offsets, - tups_size, nitups, bstrategy); + tups_size, nitups, bstrategy, isbuild); /* be tidy */ for (i = 0; i < nitups; i++) diff --git a/src/backend/access/hash/hashpage.c b/src/backend/access/hash/hashpage.c index b8e5bd005e5..f5e310ab2b3 100644 --- a/src/backend/access/hash/hashpage.c +++ b/src/backend/access/hash/hashpage.c @@ -45,7 +45,7 @@ static void _hash_splitbucket(Relation rel, Buffer metabuf, Buffer nbuf, HTAB *htab, uint32 maxbucket, - uint32 highmask, uint32 lowmask); + uint32 highmask, uint32 lowmask, bool isbuild); static void log_split_page(Relation rel, Buffer buf); @@ -324,7 +324,7 @@ _hash_dropscanbuf(Relation rel, HashScanOpaque so) * multiple buffer locks is ignored. */ uint32 -_hash_init(Relation rel, double num_tuples, ForkNumber forkNum) +_hash_init(Relation rel, double num_tuples, ForkNumber forkNum, bool skip_wal) { Buffer metabuf; Buffer buf; @@ -349,7 +349,7 @@ _hash_init(Relation rel, double num_tuples, ForkNumber forkNum) * init fork. Init forks for unlogged relations always need to be WAL * logged. */ - use_wal = RelationNeedsWAL(rel) || forkNum == INIT_FORKNUM; + use_wal = !skip_wal && (RelationNeedsWAL(rel) || forkNum == INIT_FORKNUM); /* * Determine the target fill factor (in tuples per bucket) for this index. @@ -611,7 +611,7 @@ _hash_pageinit(Page page, Size size) * The buffer is returned in the same state. */ void -_hash_expandtable(Relation rel, Buffer metabuf) +_hash_expandtable(Relation rel, Buffer metabuf, bool isbuild) { HashMetaPage metap; Bucket old_bucket; @@ -759,7 +759,7 @@ restart_expand: hashbucketcleanup(rel, old_bucket, buf_oblkno, start_oblkno, NULL, maxbucket, highmask, lowmask, NULL, NULL, true, - NULL, NULL); + NULL, NULL, isbuild); _hash_dropbuf(rel, buf_oblkno); @@ -897,7 +897,7 @@ restart_expand: MarkBufferDirty(buf_nblkno); /* XLOG stuff */ - if (RelationNeedsWAL(rel)) + if (RelationNeedsWAL(rel) && !isbuild) { xl_hash_split_allocate_page xlrec; XLogRecPtr recptr; @@ -948,7 +948,7 @@ restart_expand: _hash_splitbucket(rel, metabuf, old_bucket, new_bucket, buf_oblkno, buf_nblkno, NULL, - maxbucket, highmask, lowmask); + maxbucket, highmask, lowmask, isbuild); /* all done, now release the pins on primary buckets. */ _hash_dropbuf(rel, buf_oblkno); @@ -1079,7 +1079,8 @@ _hash_splitbucket(Relation rel, HTAB *htab, uint32 maxbucket, uint32 highmask, - uint32 lowmask) + uint32 lowmask, + bool isbuild) { Buffer bucket_obuf; Buffer bucket_nbuf; @@ -1186,7 +1187,8 @@ _hash_splitbucket(Relation rel, _hash_pgaddmultitup(rel, nbuf, itups, itup_offsets, nitups); MarkBufferDirty(nbuf); /* log the split operation before releasing the lock */ - log_split_page(rel, nbuf); + if (RelationNeedsWAL(rel) && !isbuild) + log_split_page(rel, nbuf); END_CRIT_SECTION(); @@ -1200,7 +1202,7 @@ _hash_splitbucket(Relation rel, all_tups_size = 0; /* chain to a new overflow page */ - nbuf = _hash_addovflpage(rel, metabuf, nbuf, (nbuf == bucket_nbuf)); + nbuf = _hash_addovflpage(rel, metabuf, nbuf, (nbuf == bucket_nbuf), isbuild); npage = BufferGetPage(nbuf); nopaque = HashPageGetOpaque(npage); } @@ -1237,7 +1239,9 @@ _hash_splitbucket(Relation rel, _hash_pgaddmultitup(rel, nbuf, itups, itup_offsets, nitups); MarkBufferDirty(nbuf); /* log the split operation before releasing the lock */ - log_split_page(rel, nbuf); + + if (RelationNeedsWAL(rel) && !isbuild) + log_split_page(rel, nbuf); END_CRIT_SECTION(); @@ -1294,7 +1298,7 @@ _hash_splitbucket(Relation rel, MarkBufferDirty(bucket_obuf); MarkBufferDirty(bucket_nbuf); - if (RelationNeedsWAL(rel)) + if (RelationNeedsWAL(rel) && !isbuild) { XLogRecPtr recptr; xl_hash_split_complete xlrec; @@ -1331,7 +1335,7 @@ _hash_splitbucket(Relation rel, hashbucketcleanup(rel, obucket, bucket_obuf, BufferGetBlockNumber(bucket_obuf), NULL, maxbucket, highmask, lowmask, NULL, NULL, true, - NULL, NULL); + NULL, NULL, isbuild); } else { @@ -1455,7 +1459,7 @@ _hash_finish_split(Relation rel, Buffer metabuf, Buffer obuf, Bucket obucket, _hash_splitbucket(rel, metabuf, obucket, nbucket, obuf, bucket_nbuf, tidhtab, - maxbucket, highmask, lowmask); + maxbucket, highmask, lowmask, false); _hash_dropbuf(rel, bucket_nbuf); hash_destroy(tidhtab); diff --git a/src/backend/access/hash/hashsort.c b/src/backend/access/hash/hashsort.c index 6e8c0e68a92..870396841de 100644 --- a/src/backend/access/hash/hashsort.c +++ b/src/backend/access/hash/hashsort.c @@ -61,6 +61,8 @@ _h_spoolinit(Relation heap, Relation index, uint32 num_buckets) { HSpool *hspool = (HSpool *) palloc0(sizeof(HSpool)); + elog(WARNING, "spool init"); + hspool->index = index; /* @@ -146,7 +148,7 @@ _h_indexbuild(HSpool *hspool, Relation heapRel) #endif /* the tuples are sorted by hashkey, so pass 'sorted' as true */ - _hash_doinsert(hspool->index, itup, heapRel, true); + _hash_doinsert(hspool->index, itup, heapRel, true, true); /* allow insertion phase to be interrupted, and track progress */ CHECK_FOR_INTERRUPTS(); diff --git a/src/include/access/hash.h b/src/include/access/hash.h index 073ad29b19b..f4afbc78f38 100644 --- a/src/include/access/hash.h +++ b/src/include/access/hash.h @@ -394,7 +394,7 @@ extern StrategyNumber hashtranslatecmptype(CompareType cmptype, Oid opfamily); /* hashinsert.c */ extern void _hash_doinsert(Relation rel, IndexTuple itup, Relation heapRel, - bool sorted); + bool sorted, bool isbuild); extern OffsetNumber _hash_pgaddtup(Relation rel, Buffer buf, Size itemsize, IndexTuple itup, bool appendtup); @@ -402,15 +402,15 @@ extern void _hash_pgaddmultitup(Relation rel, Buffer buf, IndexTuple *itups, OffsetNumber *itup_offsets, uint16 nitups); /* hashovfl.c */ -extern Buffer _hash_addovflpage(Relation rel, Buffer metabuf, Buffer buf, bool retain_pin); +extern Buffer _hash_addovflpage(Relation rel, Buffer metabuf, Buffer buf, bool retain_pin, bool isbuild); extern BlockNumber _hash_freeovflpage(Relation rel, Buffer bucketbuf, Buffer ovflbuf, Buffer wbuf, IndexTuple *itups, OffsetNumber *itup_offsets, - Size *tups_size, uint16 nitups, BufferAccessStrategy bstrategy); + Size *tups_size, uint16 nitups, BufferAccessStrategy bstrategy, bool isbuild); extern void _hash_initbitmapbuffer(Buffer buf, uint16 bmsize, bool initpage); extern void _hash_squeezebucket(Relation rel, Bucket bucket, BlockNumber bucket_blkno, Buffer bucket_buf, - BufferAccessStrategy bstrategy); + BufferAccessStrategy bstrategy, bool isbuild); extern uint32 _hash_ovflblkno_to_bitno(HashMetaPage metap, BlockNumber ovflblkno); /* hashpage.c */ @@ -435,11 +435,11 @@ extern void _hash_relbuf(Relation rel, Buffer buf); extern void _hash_dropbuf(Relation rel, Buffer buf); extern void _hash_dropscanbuf(Relation rel, HashScanOpaque so); extern uint32 _hash_init(Relation rel, double num_tuples, - ForkNumber forkNum); + ForkNumber forkNum, bool skip_wal); extern void _hash_init_metabuffer(Buffer buf, double num_tuples, RegProcedure procid, uint16 ffactor, bool initpage); extern void _hash_pageinit(Page page, Size size); -extern void _hash_expandtable(Relation rel, Buffer metabuf); +extern void _hash_expandtable(Relation rel, Buffer metabuf, bool isbuild); extern void _hash_finish_split(Relation rel, Buffer metabuf, Buffer obuf, Bucket obucket, uint32 maxbucket, uint32 highmask, uint32 lowmask); @@ -485,6 +485,6 @@ extern void hashbucketcleanup(Relation rel, Bucket cur_bucket, uint32 maxbucket, uint32 highmask, uint32 lowmask, double *tuples_removed, double *num_index_tuples, bool split_cleanup, - IndexBulkDeleteCallback callback, void *callback_state); + IndexBulkDeleteCallback callback, void *callback_state, bool isbuild); #endif /* HASH_H */ -- 2.43.0