Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a236765

Browse files
author
Amit Kapila
committed
Revert "Avoid creation of the free space map for small heap relations."
This reverts commit ac88d29.
1 parent ac88d29 commit a236765

File tree

16 files changed

+102
-576
lines changed

16 files changed

+102
-576
lines changed

contrib/pageinspect/expected/page.out

Lines changed: 38 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,48 @@
11
CREATE EXTENSION pageinspect;
2-
CREATE TABLE test_rel_forks (a int);
3-
-- Make sure there are enough blocks in the heap for the FSM to be created.
4-
INSERT INTO test_rel_forks SELECT i from generate_series(1,1000) i;
5-
-- set up FSM and VM
6-
VACUUM test_rel_forks;
2+
CREATE TABLE test1 (a int, b int);
3+
INSERT INTO test1 VALUES (16777217, 131584);
4+
VACUUM test1; -- set up FSM
75
-- The page contents can vary, so just test that it can be read
86
-- successfully, but don't keep the output.
9-
SELECT octet_length(get_raw_page('test_rel_forks', 'main', 0)) AS main_0;
7+
SELECT octet_length(get_raw_page('test1', 'main', 0)) AS main_0;
108
main_0
119
--------
1210
8192
1311
(1 row)
1412

15-
SELECT octet_length(get_raw_page('test_rel_forks', 'main', 100)) AS main_100;
16-
ERROR: block number 100 is out of range for relation "test_rel_forks"
17-
SELECT octet_length(get_raw_page('test_rel_forks', 'fsm', 0)) AS fsm_0;
13+
SELECT octet_length(get_raw_page('test1', 'main', 1)) AS main_1;
14+
ERROR: block number 1 is out of range for relation "test1"
15+
SELECT octet_length(get_raw_page('test1', 'fsm', 0)) AS fsm_0;
1816
fsm_0
1917
-------
2018
8192
2119
(1 row)
2220

23-
SELECT octet_length(get_raw_page('test_rel_forks', 'fsm', 10)) AS fsm_10;
24-
ERROR: block number 10 is out of range for relation "test_rel_forks"
25-
SELECT octet_length(get_raw_page('test_rel_forks', 'vm', 0)) AS vm_0;
21+
SELECT octet_length(get_raw_page('test1', 'fsm', 1)) AS fsm_1;
22+
fsm_1
23+
-------
24+
8192
25+
(1 row)
26+
27+
SELECT octet_length(get_raw_page('test1', 'vm', 0)) AS vm_0;
2628
vm_0
2729
------
2830
8192
2931
(1 row)
3032

31-
SELECT octet_length(get_raw_page('test_rel_forks', 'vm', 1)) AS vm_1;
32-
ERROR: block number 1 is out of range for relation "test_rel_forks"
33+
SELECT octet_length(get_raw_page('test1', 'vm', 1)) AS vm_1;
34+
ERROR: block number 1 is out of range for relation "test1"
3335
SELECT octet_length(get_raw_page('xxx', 'main', 0));
3436
ERROR: relation "xxx" does not exist
35-
SELECT octet_length(get_raw_page('test_rel_forks', 'xxx', 0));
37+
SELECT octet_length(get_raw_page('test1', 'xxx', 0));
3638
ERROR: invalid fork name
3739
HINT: Valid fork names are "main", "fsm", "vm", and "init".
38-
SELECT * FROM fsm_page_contents(get_raw_page('test_rel_forks', 'fsm', 0));
39-
fsm_page_contents
40-
-------------------
41-
0: 147 +
42-
1: 147 +
43-
3: 147 +
44-
7: 147 +
45-
15: 147 +
46-
31: 147 +
47-
63: 147 +
48-
127: 147 +
49-
255: 147 +
50-
511: 147 +
51-
1023: 147 +
52-
2047: 147 +
53-
4095: 147 +
54-
fp_next_slot: 0 +
55-
56-
(1 row)
57-
58-
SELECT get_raw_page('test_rel_forks', 0) = get_raw_page('test_rel_forks', 'main', 0);
40+
SELECT get_raw_page('test1', 0) = get_raw_page('test1', 'main', 0);
5941
?column?
6042
----------
6143
t
6244
(1 row)
6345

64-
DROP TABLE test_rel_forks;
65-
CREATE TABLE test1 (a int, b int);
66-
INSERT INTO test1 VALUES (16777217, 131584);
6746
SELECT pagesize, version FROM page_header(get_raw_page('test1', 0));
6847
pagesize | version
6948
----------+---------
@@ -83,6 +62,26 @@ SELECT tuple_data_split('test1'::regclass, t_data, t_infomask, t_infomask2, t_bi
8362
{"\\x01000001","\\x00020200"}
8463
(1 row)
8564

65+
SELECT * FROM fsm_page_contents(get_raw_page('test1', 'fsm', 0));
66+
fsm_page_contents
67+
-------------------
68+
0: 254 +
69+
1: 254 +
70+
3: 254 +
71+
7: 254 +
72+
15: 254 +
73+
31: 254 +
74+
63: 254 +
75+
127: 254 +
76+
255: 254 +
77+
511: 254 +
78+
1023: 254 +
79+
2047: 254 +
80+
4095: 254 +
81+
fp_next_slot: 0 +
82+
83+
(1 row)
84+
8685
DROP TABLE test1;
8786
-- check that using any of these functions with a partitioned table or index
8887
-- would fail

contrib/pageinspect/sql/page.sql

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,26 @@
11
CREATE EXTENSION pageinspect;
22

3-
CREATE TABLE test_rel_forks (a int);
4-
-- Make sure there are enough blocks in the heap for the FSM to be created.
5-
INSERT INTO test_rel_forks SELECT i from generate_series(1,1000) i;
3+
CREATE TABLE test1 (a int, b int);
4+
INSERT INTO test1 VALUES (16777217, 131584);
65

7-
-- set up FSM and VM
8-
VACUUM test_rel_forks;
6+
VACUUM test1; -- set up FSM
97

108
-- The page contents can vary, so just test that it can be read
119
-- successfully, but don't keep the output.
1210

13-
SELECT octet_length(get_raw_page('test_rel_forks', 'main', 0)) AS main_0;
14-
SELECT octet_length(get_raw_page('test_rel_forks', 'main', 100)) AS main_100;
11+
SELECT octet_length(get_raw_page('test1', 'main', 0)) AS main_0;
12+
SELECT octet_length(get_raw_page('test1', 'main', 1)) AS main_1;
1513

16-
SELECT octet_length(get_raw_page('test_rel_forks', 'fsm', 0)) AS fsm_0;
17-
SELECT octet_length(get_raw_page('test_rel_forks', 'fsm', 10)) AS fsm_10;
14+
SELECT octet_length(get_raw_page('test1', 'fsm', 0)) AS fsm_0;
15+
SELECT octet_length(get_raw_page('test1', 'fsm', 1)) AS fsm_1;
1816

19-
SELECT octet_length(get_raw_page('test_rel_forks', 'vm', 0)) AS vm_0;
20-
SELECT octet_length(get_raw_page('test_rel_forks', 'vm', 1)) AS vm_1;
17+
SELECT octet_length(get_raw_page('test1', 'vm', 0)) AS vm_0;
18+
SELECT octet_length(get_raw_page('test1', 'vm', 1)) AS vm_1;
2119

2220
SELECT octet_length(get_raw_page('xxx', 'main', 0));
23-
SELECT octet_length(get_raw_page('test_rel_forks', 'xxx', 0));
24-
25-
SELECT * FROM fsm_page_contents(get_raw_page('test_rel_forks', 'fsm', 0));
26-
27-
SELECT get_raw_page('test_rel_forks', 0) = get_raw_page('test_rel_forks', 'main', 0);
21+
SELECT octet_length(get_raw_page('test1', 'xxx', 0));
2822

29-
DROP TABLE test_rel_forks;
30-
31-
CREATE TABLE test1 (a int, b int);
32-
INSERT INTO test1 VALUES (16777217, 131584);
23+
SELECT get_raw_page('test1', 0) = get_raw_page('test1', 'main', 0);
3324

3425
SELECT pagesize, version FROM page_header(get_raw_page('test1', 0));
3526

@@ -38,6 +29,8 @@ SELECT page_checksum(get_raw_page('test1', 0), 0) IS NOT NULL AS silly_checksum_
3829
SELECT tuple_data_split('test1'::regclass, t_data, t_infomask, t_infomask2, t_bits)
3930
FROM heap_page_items(get_raw_page('test1', 0));
4031

32+
SELECT * FROM fsm_page_contents(get_raw_page('test1', 'fsm', 0));
33+
4134
DROP TABLE test1;
4235

4336
-- check that using any of these functions with a partitioned table or index

doc/src/sgml/storage.sgml

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -590,13 +590,12 @@ tuple would otherwise be too big.
590590
<indexterm><primary>FSM</primary><see>Free Space Map</see></indexterm>
591591

592592
<para>
593-
Each heap relation, unless it is very small, and each index relation, except
594-
for hash indexes, has a Free Space Map (FSM) to keep track of available
595-
space in the relation. It's stored alongside the main relation data in a
596-
separate relation fork, named after the filenode number of the relation, plus
597-
a <literal>_fsm</literal> suffix. For example, if the filenode of a relation
598-
is 12345, the FSM is stored in a file called <filename>12345_fsm</filename>,
599-
in the same directory as the main relation file.
593+
Each heap and index relation, except for hash indexes, has a Free Space Map
594+
(FSM) to keep track of available space in the relation. It's stored
595+
alongside the main relation data in a separate relation fork, named after the
596+
filenode number of the relation, plus a <literal>_fsm</literal> suffix. For example,
597+
if the filenode of a relation is 12345, the FSM is stored in a file called
598+
<filename>12345_fsm</filename>, in the same directory as the main relation file.
600599
</para>
601600

602601
<para>

src/backend/access/brin/brin.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1150,7 +1150,7 @@ terminate_brin_buildstate(BrinBuildState *state)
11501150
freespace = PageGetFreeSpace(page);
11511151
blk = BufferGetBlockNumber(state->bs_currentInsertBuf);
11521152
ReleaseBuffer(state->bs_currentInsertBuf);
1153-
RecordPageWithFreeSpace(state->bs_irel, blk, freespace, InvalidBlockNumber);
1153+
RecordPageWithFreeSpace(state->bs_irel, blk, freespace);
11541154
FreeSpaceMapVacuumRange(state->bs_irel, blk, blk + 1);
11551155
}
11561156

src/backend/access/brin/brin_pageops.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ brin_doupdate(Relation idxrel, BlockNumber pagesPerRange,
310310

311311
if (extended)
312312
{
313-
RecordPageWithFreeSpace(idxrel, newblk, freespace, InvalidBlockNumber);
313+
RecordPageWithFreeSpace(idxrel, newblk, freespace);
314314
FreeSpaceMapVacuumRange(idxrel, newblk, newblk + 1);
315315
}
316316

@@ -461,7 +461,7 @@ brin_doinsert(Relation idxrel, BlockNumber pagesPerRange,
461461

462462
if (extended)
463463
{
464-
RecordPageWithFreeSpace(idxrel, blk, freespace, InvalidBlockNumber);
464+
RecordPageWithFreeSpace(idxrel, blk, freespace);
465465
FreeSpaceMapVacuumRange(idxrel, blk, blk + 1);
466466
}
467467

@@ -654,7 +654,7 @@ brin_page_cleanup(Relation idxrel, Buffer buf)
654654

655655
/* Measure free space and record it */
656656
RecordPageWithFreeSpace(idxrel, BufferGetBlockNumber(buf),
657-
br_page_get_freespace(page), InvalidBlockNumber);
657+
br_page_get_freespace(page));
658658
}
659659

660660
/*
@@ -703,7 +703,7 @@ brin_getinsertbuffer(Relation irel, Buffer oldbuf, Size itemsz,
703703
/* Choose initial target page, re-using existing target if known */
704704
newblk = RelationGetTargetBlock(irel);
705705
if (newblk == InvalidBlockNumber)
706-
newblk = GetPageWithFreeSpace(irel, itemsz, true);
706+
newblk = GetPageWithFreeSpace(irel, itemsz);
707707

708708
/*
709709
* Loop until we find a page with sufficient free space. By the time we
@@ -895,7 +895,7 @@ brin_initialize_empty_new_buffer(Relation idxrel, Buffer buffer)
895895
* pages whose FSM records were forgotten in a crash.
896896
*/
897897
RecordPageWithFreeSpace(idxrel, BufferGetBlockNumber(buffer),
898-
br_page_get_freespace(page), InvalidBlockNumber);
898+
br_page_get_freespace(page));
899899
}
900900

901901

src/backend/access/heap/hio.c

Lines changed: 17 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -239,14 +239,8 @@ RelationAddExtraBlocks(Relation relation, BulkInsertState bistate)
239239
* Immediately update the bottom level of the FSM. This has a good
240240
* chance of making this page visible to other concurrently inserting
241241
* backends, and we want that to happen without delay.
242-
*
243-
* Since we know the table will end up with extraBlocks additional
244-
* pages, we pass the final number to avoid possible unnecessary
245-
* system calls and to make sure the FSM is created when we add the
246-
* first new page.
247242
*/
248-
RecordPageWithFreeSpace(relation, blockNum, freespace,
249-
firstBlock + extraBlocks);
243+
RecordPageWithFreeSpace(relation, blockNum, freespace);
250244
}
251245
while (--extraBlocks > 0);
252246

@@ -383,9 +377,20 @@ RelationGetBufferForTuple(Relation relation, Size len,
383377
* We have no cached target page, so ask the FSM for an initial
384378
* target.
385379
*/
386-
targetBlock = GetPageWithFreeSpace(relation,
387-
len + saveFreeSpace,
388-
false);
380+
targetBlock = GetPageWithFreeSpace(relation, len + saveFreeSpace);
381+
382+
/*
383+
* If the FSM knows nothing of the rel, try the last page before we
384+
* give up and extend. This avoids one-tuple-per-page syndrome during
385+
* bootstrapping or in a recently-started system.
386+
*/
387+
if (targetBlock == InvalidBlockNumber)
388+
{
389+
BlockNumber nblocks = RelationGetNumberOfBlocks(relation);
390+
391+
if (nblocks > 0)
392+
targetBlock = nblocks - 1;
393+
}
389394
}
390395

391396
loop:
@@ -479,14 +484,6 @@ RelationGetBufferForTuple(Relation relation, Size len,
479484
{
480485
/* use this page as future insert target, too */
481486
RelationSetTargetBlock(relation, targetBlock);
482-
483-
/*
484-
* In case we used an in-memory map of available blocks, reset it
485-
* for next use.
486-
*/
487-
if (targetBlock < HEAP_FSM_CREATION_THRESHOLD)
488-
FSMClearLocalMap();
489-
490487
return buffer;
491488
}
492489

@@ -546,12 +543,9 @@ RelationGetBufferForTuple(Relation relation, Size len,
546543

547544
/*
548545
* Check if some other backend has extended a block for us while
549-
* we were waiting on the lock. We only check the FSM -- if there
550-
* isn't one we don't recheck the number of blocks.
546+
* we were waiting on the lock.
551547
*/
552-
targetBlock = GetPageWithFreeSpace(relation,
553-
len + saveFreeSpace,
554-
true);
548+
targetBlock = GetPageWithFreeSpace(relation, len + saveFreeSpace);
555549

556550
/*
557551
* If some other waiter has already extended the relation, we
@@ -631,12 +625,5 @@ RelationGetBufferForTuple(Relation relation, Size len,
631625
*/
632626
RelationSetTargetBlock(relation, BufferGetBlockNumber(buffer));
633627

634-
/*
635-
* In case we used an in-memory map of available blocks, reset it for next
636-
* use. We do this unconditionally since after relation extension we
637-
* can't skip this based on the targetBlock.
638-
*/
639-
FSMClearLocalMap();
640-
641628
return buffer;
642629
}

0 commit comments

Comments
 (0)