mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-08-18 13:13:24 +02:00
This avoids a very significant amount of buffer manager traffic and contention when scanning hash indexes, because it's no longer necessary to lock and pin the metapage for every scan. We do need some way of figuring out when the cache is too stale to use any more, so that when we lock the primary bucket page to which the cached metapage points us, we can tell whether a split has occurred since we cached the metapage data. To do that, we use the hash_prevblkno field in the primary bucket page, which would otherwise always be set to InvalidBuffer. This patch contains code so that it will continue working (although less efficiently) with hash indexes built before this change, but perhaps we should consider bumping the hash version and ripping out the compatibility code. That decision can be made later, though. Mithun Cy, reviewed by Jesper Pedersen, Amit Kapila, and by me. Before committing, I made a number of cosmetic changes to the last posted version of the patch, adjusted _hash_getcachedmetap to be more careful about order of operation, and made some necessary updates to the pageinspect documentation and regression tests.
170 lines
6.4 KiB
Plaintext
170 lines
6.4 KiB
Plaintext
CREATE TABLE test_hash (a int, b text);
|
|
INSERT INTO test_hash VALUES (1, 'one');
|
|
CREATE INDEX test_hash_a_idx ON test_hash USING hash (a);
|
|
WARNING: hash indexes are not WAL-logged and their use is discouraged
|
|
\x
|
|
SELECT hash_page_type(get_raw_page('test_hash_a_idx', 0));
|
|
-[ RECORD 1 ]--+---------
|
|
hash_page_type | metapage
|
|
|
|
SELECT hash_page_type(get_raw_page('test_hash_a_idx', 1));
|
|
-[ RECORD 1 ]--+-------
|
|
hash_page_type | bucket
|
|
|
|
SELECT hash_page_type(get_raw_page('test_hash_a_idx', 2));
|
|
-[ RECORD 1 ]--+-------
|
|
hash_page_type | bucket
|
|
|
|
SELECT hash_page_type(get_raw_page('test_hash_a_idx', 3));
|
|
-[ RECORD 1 ]--+-------
|
|
hash_page_type | bucket
|
|
|
|
SELECT hash_page_type(get_raw_page('test_hash_a_idx', 4));
|
|
-[ RECORD 1 ]--+-------
|
|
hash_page_type | bucket
|
|
|
|
SELECT hash_page_type(get_raw_page('test_hash_a_idx', 5));
|
|
-[ RECORD 1 ]--+-------
|
|
hash_page_type | bitmap
|
|
|
|
SELECT hash_page_type(get_raw_page('test_hash_a_idx', 6));
|
|
ERROR: block number 6 is out of range for relation "test_hash_a_idx"
|
|
SELECT * FROM hash_bitmap_info('test_hash_a_idx', 0);
|
|
ERROR: page is not an overflow page
|
|
DETAIL: Expected 00000001, got 00000008.
|
|
SELECT * FROM hash_bitmap_info('test_hash_a_idx', 1);
|
|
ERROR: page is not an overflow page
|
|
DETAIL: Expected 00000001, got 00000002.
|
|
SELECT * FROM hash_bitmap_info('test_hash_a_idx', 2);
|
|
ERROR: page is not an overflow page
|
|
DETAIL: Expected 00000001, got 00000002.
|
|
SELECT * FROM hash_bitmap_info('test_hash_a_idx', 3);
|
|
ERROR: page is not an overflow page
|
|
DETAIL: Expected 00000001, got 00000002.
|
|
SELECT * FROM hash_bitmap_info('test_hash_a_idx', 4);
|
|
ERROR: page is not an overflow page
|
|
DETAIL: Expected 00000001, got 00000002.
|
|
SELECT * FROM hash_bitmap_info('test_hash_a_idx', 5);
|
|
ERROR: page is not an overflow page
|
|
DETAIL: Expected 00000001, got 00000004.
|
|
SELECT magic, version, ntuples, bsize, bmsize, bmshift, maxbucket, highmask,
|
|
lowmask, ovflpoint, firstfree, nmaps, procid, spares, mapp FROM
|
|
hash_metapage_info(get_raw_page('test_hash_a_idx', 0));
|
|
-[ RECORD 1 ]----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
magic | 105121344
|
|
version | 2
|
|
ntuples | 1
|
|
bsize | 8152
|
|
bmsize | 4096
|
|
bmshift | 15
|
|
maxbucket | 3
|
|
highmask | 7
|
|
lowmask | 3
|
|
ovflpoint | 2
|
|
firstfree | 0
|
|
nmaps | 1
|
|
procid | 450
|
|
spares | {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
|
|
mapp | {5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
|
|
|
|
SELECT magic, version, ntuples, bsize, bmsize, bmshift, maxbucket, highmask,
|
|
lowmask, ovflpoint, firstfree, nmaps, procid, spares, mapp FROM
|
|
hash_metapage_info(get_raw_page('test_hash_a_idx', 1));
|
|
ERROR: page is not a hash meta page
|
|
SELECT magic, version, ntuples, bsize, bmsize, bmshift, maxbucket, highmask,
|
|
lowmask, ovflpoint, firstfree, nmaps, procid, spares, mapp FROM
|
|
hash_metapage_info(get_raw_page('test_hash_a_idx', 2));
|
|
ERROR: page is not a hash meta page
|
|
SELECT magic, version, ntuples, bsize, bmsize, bmshift, maxbucket, highmask,
|
|
lowmask, ovflpoint, firstfree, nmaps, procid, spares, mapp FROM
|
|
hash_metapage_info(get_raw_page('test_hash_a_idx', 3));
|
|
ERROR: page is not a hash meta page
|
|
SELECT magic, version, ntuples, bsize, bmsize, bmshift, maxbucket, highmask,
|
|
lowmask, ovflpoint, firstfree, nmaps, procid, spares, mapp FROM
|
|
hash_metapage_info(get_raw_page('test_hash_a_idx', 4));
|
|
ERROR: page is not a hash meta page
|
|
SELECT magic, version, ntuples, bsize, bmsize, bmshift, maxbucket, highmask,
|
|
lowmask, ovflpoint, firstfree, nmaps, procid, spares, mapp FROM
|
|
hash_metapage_info(get_raw_page('test_hash_a_idx', 5));
|
|
ERROR: page is not a hash meta page
|
|
SELECT live_items, dead_items, page_size, hasho_prevblkno, hasho_nextblkno,
|
|
hasho_bucket, hasho_flag, hasho_page_id FROM
|
|
hash_page_stats(get_raw_page('test_hash_a_idx', 0));
|
|
ERROR: page is not a hash bucket or overflow page
|
|
SELECT live_items, dead_items, page_size, hasho_prevblkno, hasho_nextblkno,
|
|
hasho_bucket, hasho_flag, hasho_page_id FROM
|
|
hash_page_stats(get_raw_page('test_hash_a_idx', 1));
|
|
-[ RECORD 1 ]---+-----------
|
|
live_items | 0
|
|
dead_items | 0
|
|
page_size | 8192
|
|
hasho_prevblkno | 3
|
|
hasho_nextblkno | 4294967295
|
|
hasho_bucket | 0
|
|
hasho_flag | 2
|
|
hasho_page_id | 65408
|
|
|
|
SELECT live_items, dead_items, page_size, hasho_prevblkno, hasho_nextblkno,
|
|
hasho_bucket, hasho_flag, hasho_page_id FROM
|
|
hash_page_stats(get_raw_page('test_hash_a_idx', 2));
|
|
-[ RECORD 1 ]---+-----------
|
|
live_items | 0
|
|
dead_items | 0
|
|
page_size | 8192
|
|
hasho_prevblkno | 3
|
|
hasho_nextblkno | 4294967295
|
|
hasho_bucket | 1
|
|
hasho_flag | 2
|
|
hasho_page_id | 65408
|
|
|
|
SELECT live_items, dead_items, page_size, hasho_prevblkno, hasho_nextblkno,
|
|
hasho_bucket, hasho_flag, hasho_page_id FROM
|
|
hash_page_stats(get_raw_page('test_hash_a_idx', 3));
|
|
-[ RECORD 1 ]---+-----------
|
|
live_items | 1
|
|
dead_items | 0
|
|
page_size | 8192
|
|
hasho_prevblkno | 3
|
|
hasho_nextblkno | 4294967295
|
|
hasho_bucket | 2
|
|
hasho_flag | 2
|
|
hasho_page_id | 65408
|
|
|
|
SELECT live_items, dead_items, page_size, hasho_prevblkno, hasho_nextblkno,
|
|
hasho_bucket, hasho_flag, hasho_page_id FROM
|
|
hash_page_stats(get_raw_page('test_hash_a_idx', 4));
|
|
-[ RECORD 1 ]---+-----------
|
|
live_items | 0
|
|
dead_items | 0
|
|
page_size | 8192
|
|
hasho_prevblkno | 3
|
|
hasho_nextblkno | 4294967295
|
|
hasho_bucket | 3
|
|
hasho_flag | 2
|
|
hasho_page_id | 65408
|
|
|
|
SELECT live_items, dead_items, page_size, hasho_prevblkno, hasho_nextblkno,
|
|
hasho_bucket, hasho_flag, hasho_page_id FROM
|
|
hash_page_stats(get_raw_page('test_hash_a_idx', 5));
|
|
ERROR: page is not a hash bucket or overflow page
|
|
SELECT * FROM hash_page_items(get_raw_page('test_hash_a_idx', 0));
|
|
ERROR: page is not a hash bucket or overflow page
|
|
SELECT * FROM hash_page_items(get_raw_page('test_hash_a_idx', 1));
|
|
(0 rows)
|
|
|
|
SELECT * FROM hash_page_items(get_raw_page('test_hash_a_idx', 2));
|
|
(0 rows)
|
|
|
|
SELECT * FROM hash_page_items(get_raw_page('test_hash_a_idx', 3));
|
|
-[ RECORD 1 ]----------
|
|
itemoffset | 1
|
|
ctid | (0,1)
|
|
data | 2389907270
|
|
|
|
SELECT * FROM hash_page_items(get_raw_page('test_hash_a_idx', 4));
|
|
(0 rows)
|
|
|
|
SELECT * FROM hash_page_items(get_raw_page('test_hash_a_idx', 5));
|
|
ERROR: page is not a hash bucket or overflow page
|
|
DROP TABLE test_hash;
|