Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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

+38-39
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

+13-20
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

+6-7
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

+1-1
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

+5-5
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

+17-30
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)