Skip to content

Commit 861f86b

Browse files
author
Amit Kapila
committed
Use REGBUF_NO_CHANGE at one more place in the hash index.
Commit 00d7fb5 started to use REGBUF_NO_CHANGE at a few places in the code where we register the buffer before marking it dirty but missed updating one of the code flows in the hash index where we free the overflow page without any live tuples on it. Author: Amit Kapila and Hayato Kuroda Discussion: http://postgr.es/m/f045c8f7-ee24-ead6-3679-c04a43d21351@gmail.com
1 parent 7606175 commit 861f86b

File tree

4 files changed

+91
-2
lines changed

4 files changed

+91
-2
lines changed

src/backend/access/hash/hash_xlog.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -655,7 +655,10 @@ hash_xlog_squeeze_page(XLogReaderState *record)
655655
*/
656656
(void) XLogReadBufferForRedoExtended(record, 0, RBM_NORMAL, true, &bucketbuf);
657657

658-
action = XLogReadBufferForRedo(record, 1, &writebuf);
658+
if (xldata->ntups > 0 || xldata->is_prev_bucket_same_wrt)
659+
action = XLogReadBufferForRedo(record, 1, &writebuf);
660+
else
661+
action = BLK_NOTFOUND;
659662
}
660663

661664
/* replay the record for adding entries in overflow buffer */

src/backend/access/hash/hashovfl.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -668,14 +668,31 @@ _hash_freeovflpage(Relation rel, Buffer bucketbuf, Buffer ovflbuf,
668668
XLogRegisterBuffer(0, bucketbuf, flags);
669669
}
670670

671-
XLogRegisterBuffer(1, wbuf, REGBUF_STANDARD);
672671
if (xlrec.ntups > 0)
673672
{
673+
XLogRegisterBuffer(1, wbuf, REGBUF_STANDARD);
674674
XLogRegisterBufData(1, (char *) itup_offsets,
675675
nitups * sizeof(OffsetNumber));
676676
for (i = 0; i < nitups; i++)
677677
XLogRegisterBufData(1, (char *) itups[i], tups_size[i]);
678678
}
679+
else if (xlrec.is_prim_bucket_same_wrt || xlrec.is_prev_bucket_same_wrt)
680+
{
681+
uint8 wbuf_flags;
682+
683+
/*
684+
* A write buffer needs to be registered even if no tuples are
685+
* added to it to ensure that we can acquire a cleanup lock on it
686+
* if it is the same as primary bucket buffer or update the
687+
* nextblkno if it is same as the previous bucket buffer.
688+
*/
689+
Assert(xlrec.ntups == 0);
690+
691+
wbuf_flags = REGBUF_STANDARD;
692+
if (!xlrec.is_prev_bucket_same_wrt)
693+
wbuf_flags |= REGBUF_NO_CHANGE;
694+
XLogRegisterBuffer(1, wbuf, wbuf_flags);
695+
}
679696

680697
XLogRegisterBuffer(2, ovflbuf, REGBUF_STANDARD);
681698

src/test/regress/expected/hash_index.out

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,35 @@ ALTER INDEX hash_split_index SET (fillfactor = 10);
271271
REINDEX INDEX hash_split_index;
272272
-- Clean up.
273273
DROP TABLE hash_split_heap;
274+
-- Testcases for removing overflow pages.
275+
CREATE TABLE hash_cleanup_heap(keycol INT);
276+
CREATE INDEX hash_cleanup_index on hash_cleanup_heap USING HASH (keycol);
277+
-- Insert tuples to both the primary bucket page and overflow pages.
278+
INSERT INTO hash_cleanup_heap SELECT 1 FROM generate_series(1, 500) as i;
279+
-- Fill overflow pages by "dead" tuples.
280+
BEGIN;
281+
INSERT INTO hash_cleanup_heap SELECT 1 FROM generate_series(1, 1000) as i;
282+
ROLLBACK;
283+
-- Checkpoint will ensure that all hash buffers are cleaned before we try
284+
-- to remove overflow pages.
285+
CHECKPOINT;
286+
-- This will squeeze the bucket and remove overflow pages.
287+
VACUUM hash_cleanup_heap;
288+
TRUNCATE hash_cleanup_heap;
289+
-- Insert a few tuples so that the primary bucket page doesn't get full and
290+
-- tuples can be moved to it.
291+
INSERT INTO hash_cleanup_heap SELECT 1 FROM generate_series(1, 50) as i;
292+
-- Fill overflow pages by "dead" tuples.
293+
BEGIN;
294+
INSERT INTO hash_cleanup_heap SELECT 1 FROM generate_series(1, 1500) as i;
295+
ROLLBACK;
296+
-- And insert some tuples again. During squeeze operation, these will be moved
297+
-- to the primary bucket allowing to test freeing intermediate overflow pages.
298+
INSERT INTO hash_cleanup_heap SELECT 1 FROM generate_series(1, 500) as i;
299+
CHECKPOINT;
300+
VACUUM hash_cleanup_heap;
301+
-- Clean up.
302+
DROP TABLE hash_cleanup_heap;
274303
-- Index on temp table.
275304
CREATE TEMP TABLE hash_temp_heap (x int, y int);
276305
INSERT INTO hash_temp_heap VALUES (1,1);

src/test/regress/sql/hash_index.sql

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,46 @@ REINDEX INDEX hash_split_index;
247247
-- Clean up.
248248
DROP TABLE hash_split_heap;
249249

250+
-- Testcases for removing overflow pages.
251+
CREATE TABLE hash_cleanup_heap(keycol INT);
252+
CREATE INDEX hash_cleanup_index on hash_cleanup_heap USING HASH (keycol);
253+
254+
-- Insert tuples to both the primary bucket page and overflow pages.
255+
INSERT INTO hash_cleanup_heap SELECT 1 FROM generate_series(1, 500) as i;
256+
257+
-- Fill overflow pages by "dead" tuples.
258+
BEGIN;
259+
INSERT INTO hash_cleanup_heap SELECT 1 FROM generate_series(1, 1000) as i;
260+
ROLLBACK;
261+
262+
-- Checkpoint will ensure that all hash buffers are cleaned before we try
263+
-- to remove overflow pages.
264+
CHECKPOINT;
265+
266+
-- This will squeeze the bucket and remove overflow pages.
267+
VACUUM hash_cleanup_heap;
268+
269+
TRUNCATE hash_cleanup_heap;
270+
271+
-- Insert a few tuples so that the primary bucket page doesn't get full and
272+
-- tuples can be moved to it.
273+
INSERT INTO hash_cleanup_heap SELECT 1 FROM generate_series(1, 50) as i;
274+
275+
-- Fill overflow pages by "dead" tuples.
276+
BEGIN;
277+
INSERT INTO hash_cleanup_heap SELECT 1 FROM generate_series(1, 1500) as i;
278+
ROLLBACK;
279+
280+
-- And insert some tuples again. During squeeze operation, these will be moved
281+
-- to the primary bucket allowing to test freeing intermediate overflow pages.
282+
INSERT INTO hash_cleanup_heap SELECT 1 FROM generate_series(1, 500) as i;
283+
284+
CHECKPOINT;
285+
VACUUM hash_cleanup_heap;
286+
287+
-- Clean up.
288+
DROP TABLE hash_cleanup_heap;
289+
250290
-- Index on temp table.
251291
CREATE TEMP TABLE hash_temp_heap (x int, y int);
252292
INSERT INTO hash_temp_heap VALUES (1,1);

0 commit comments

Comments
 (0)