Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit cc59049

Browse files
committed
Improve handling of prune/no-prune decisions by storing a page's oldest
unpruned XMAX in its header. At the cost of 4 bytes per page, this keeps us from performing heap_page_prune when there's no chance of pruning anything. Seems to be necessary per Heikki's preliminary performance testing.
1 parent 386a5d4 commit cc59049

File tree

10 files changed

+92
-59
lines changed

10 files changed

+92
-59
lines changed

contrib/pageinspect/README.pageinspect

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@ only by superusers.
2323

2424
A page image obtained with get_raw_page should be passed as argument:
2525

26-
test=# SELECT * FROM page_header(get_raw_page('pg_class',0));
27-
lsn | tli | flags | lower | upper | special | pagesize | version
28-
----------+-----+-------+-------+-------+---------+----------+---------
29-
0/3C5614 | 1 | 1 | 216 | 256 | 8192 | 8192 | 4
26+
regression=# SELECT * FROM page_header(get_raw_page('pg_class',0));
27+
lsn | tli | flags | lower | upper | special | pagesize | version | prune_xid
28+
-----------+-----+-------+-------+-------+---------+----------+---------+-----------
29+
0/24A1B50 | 1 | 1 | 232 | 368 | 8192 | 8192 | 4 | 0
3030
(1 row)
3131

32-
The returned columns correspond to the fields in the PageHeaderData-struct,
33-
see src/include/storage/bufpage.h for more details.
32+
The returned columns correspond to the fields in the PageHeaderData struct.
33+
See src/include/storage/bufpage.h for details.
3434

3535
heap_page_items
3636
---------------

contrib/pageinspect/pageinspect.sql.in

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ CREATE OR REPLACE FUNCTION page_header(IN page bytea,
2020
OUT upper smallint,
2121
OUT special smallint,
2222
OUT pagesize smallint,
23-
OUT version smallint)
23+
OUT version smallint,
24+
OUT prune_xid xid)
2425
AS 'MODULE_PATHNAME', 'page_header'
2526
LANGUAGE C STRICT;
2627

contrib/pageinspect/rawpage.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Copyright (c) 2007, PostgreSQL Global Development Group
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/contrib/pageinspect/rawpage.c,v 1.1 2007/05/17 19:11:24 momjian Exp $
11+
* $PostgreSQL: pgsql/contrib/pageinspect/rawpage.c,v 1.2 2007/09/21 21:25:42 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -110,8 +110,8 @@ page_header(PG_FUNCTION_ARGS)
110110

111111
Datum result;
112112
HeapTuple tuple;
113-
Datum values[8];
114-
bool nulls[8];
113+
Datum values[9];
114+
bool nulls[9];
115115

116116
PageHeader page;
117117
XLogRecPtr lsn;
@@ -152,6 +152,7 @@ page_header(PG_FUNCTION_ARGS)
152152
values[5] = UInt16GetDatum(page->pd_special);
153153
values[6] = UInt16GetDatum(PageGetPageSize(page));
154154
values[7] = UInt16GetDatum(PageGetPageLayoutVersion(page));
155+
values[8] = TransactionIdGetDatum(page->pd_prune_xid);
155156

156157
/* Build and return the tuple. */
157158

doc/src/sgml/storage.sgml

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/storage.sgml,v 1.18 2007/06/03 17:05:53 tgl Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/storage.sgml,v 1.19 2007/09/21 21:25:42 tgl Exp $ -->
22

33
<chapter id="storage">
44

@@ -416,7 +416,7 @@ Item
416416

417417
<row>
418418
<entry>PageHeaderData</entry>
419-
<entry>20 bytes long. Contains general information about the page, including
419+
<entry>24 bytes long. Contains general information about the page, including
420420
free space pointers.</entry>
421421
</row>
422422

@@ -449,7 +449,7 @@ data. Empty in ordinary tables.</entry>
449449

450450
<para>
451451

452-
The first 20 bytes of each page consists of a page header
452+
The first 24 bytes of each page consists of a page header
453453
(PageHeaderData). Its format is detailed in <xref
454454
linkend="pageheaderdata-table">. The first two fields track the most
455455
recent WAL entry related to this page. Next is a 2-byte field
@@ -459,7 +459,7 @@ data. Empty in ordinary tables.</entry>
459459
from the page start to the start
460460
of unallocated space, to the end of unallocated space, and to the start of
461461
the special space.
462-
The last 2 bytes of the page header,
462+
The next 2 bytes of the page header,
463463
<structfield>pd_pagesize_version</structfield>, store both the page size
464464
and a version indicator. Beginning with
465465
<productname>PostgreSQL</productname> 8.3 the version number is 4;
@@ -471,6 +471,8 @@ data. Empty in ordinary tables.</entry>
471471
versions, but the layout of heap row headers has.) The page size
472472
is basically only present as a cross-check; there is no support for having
473473
more than one page size in an installation.
474+
The last field is a hint that shows whether pruning the page is likely
475+
to be profitable: it tracks the oldest un-pruned XMAX on the page.
474476

475477
</para>
476478

@@ -530,6 +532,12 @@ data. Empty in ordinary tables.</entry>
530532
<entry>2 bytes</entry>
531533
<entry>Page size and layout version number information</entry>
532534
</row>
535+
<row>
536+
<entry>pd_prune_xid</entry>
537+
<entry>TransactionId</entry>
538+
<entry>4 bytes</entry>
539+
<entry>Oldest unpruned XMAX on page, or zero if none</entry>
540+
</row>
533541
</tbody>
534542
</tgroup>
535543
</table>

src/backend/access/heap/README.HOT

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
$PostgreSQL: pgsql/src/backend/access/heap/README.HOT,v 1.1 2007/09/20 17:56:30 tgl Exp $
1+
$PostgreSQL: pgsql/src/backend/access/heap/README.HOT,v 1.2 2007/09/21 21:25:42 tgl Exp $
22

33
Heap Only Tuples (HOT)
44

@@ -233,8 +233,8 @@ subsequent index searches. However it is unclear that this gain is
233233
large enough to accept any extra maintenance burden for.
234234

235235
The currently planned heuristic is to prune and defrag when first accessing
236-
a page that potentially has prunable tuples (flagged by the PD_PRUNABLE
237-
page hint bit) and that either has free space less than MAX(fillfactor
236+
a page that potentially has prunable tuples (as flagged by the pd_prune_xid
237+
page hint field) and that either has free space less than MAX(fillfactor
238238
target free space, BLCKSZ/10) *or* has recently had an UPDATE fail to
239239
find enough free space to store an updated tuple version. (These rules
240240
are subject to change.)

src/backend/access/heap/heapam.c

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.241 2007/09/20 17:56:30 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.242 2007/09/21 21:25:42 tgl Exp $
1212
*
1313
*
1414
* INTERFACE ROUTINES
@@ -2068,11 +2068,12 @@ heap_delete(Relation relation, ItemPointer tid,
20682068

20692069
/*
20702070
* If this transaction commits, the tuple will become DEAD sooner or
2071-
* later. Set hint bit that this page is a candidate for pruning. If
2072-
* the transaction finally aborts, the subsequent page pruning will be
2073-
* a no-op and the hint will be cleared.
2071+
* later. Set flag that this page is a candidate for pruning once our xid
2072+
* falls below the OldestXmin horizon. If the transaction finally aborts,
2073+
* the subsequent page pruning will be a no-op and the hint will be
2074+
* cleared.
20742075
*/
2075-
PageSetPrunable((Page) dp);
2076+
PageSetPrunable(dp, xid);
20762077

20772078
/* store transaction information of xact deleting the tuple */
20782079
tp.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED |
@@ -2571,16 +2572,17 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
25712572

25722573
/*
25732574
* If this transaction commits, the old tuple will become DEAD sooner or
2574-
* later. Set hint bit that this page is a candidate for pruning. If
2575-
* the transaction finally aborts, the subsequent page pruning will be
2576-
* a no-op and the hint will be cleared.
2575+
* later. Set flag that this page is a candidate for pruning once our xid
2576+
* falls below the OldestXmin horizon. If the transaction finally aborts,
2577+
* the subsequent page pruning will be a no-op and the hint will be
2578+
* cleared.
25772579
*
25782580
* XXX Should we set hint on newbuf as well? If the transaction
25792581
* aborts, there would be a prunable tuple in the newbuf; but for now
25802582
* we choose not to optimize for aborts. Note that heap_xlog_update
2581-
* must be kept in sync if this changes.
2583+
* must be kept in sync if this decision changes.
25822584
*/
2583-
PageSetPrunable(dp);
2585+
PageSetPrunable(dp, xid);
25842586

25852587
if (use_hot_update)
25862588
{
@@ -4108,7 +4110,7 @@ heap_xlog_delete(XLogRecPtr lsn, XLogRecord *record)
41084110
HeapTupleHeaderSetCmax(htup, FirstCommandId, false);
41094111

41104112
/* Mark the page as a candidate for pruning */
4111-
PageSetPrunable(page);
4113+
PageSetPrunable(page, record->xl_xid);
41124114

41134115
/* Make sure there is no forward chain link in t_ctid */
41144116
htup->t_ctid = xlrec->target.tid;
@@ -4284,7 +4286,7 @@ heap_xlog_update(XLogRecPtr lsn, XLogRecord *record, bool move, bool hot_update)
42844286
}
42854287

42864288
/* Mark the page as a candidate for pruning */
4287-
PageSetPrunable(page);
4289+
PageSetPrunable(page, record->xl_xid);
42884290

42894291
/*
42904292
* this test is ugly, but necessary to avoid thinking that insert change

src/backend/access/heap/pruneheap.c

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/heap/pruneheap.c,v 1.1 2007/09/20 17:56:30 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/heap/pruneheap.c,v 1.2 2007/09/21 21:25:42 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -63,9 +63,10 @@ heap_page_prune_opt(Relation relation, Buffer buffer, TransactionId OldestXmin)
6363
/*
6464
* Let's see if we really need pruning.
6565
*
66-
* Forget it if page is not hinted to contain something prunable
66+
* Forget it if page is not hinted to contain something prunable that's
67+
* older than OldestXmin.
6768
*/
68-
if (!PageIsPrunable(dp))
69+
if (!PageIsPrunable(dp, OldestXmin))
6970
return;
7071

7172
/*
@@ -93,6 +94,8 @@ heap_page_prune_opt(Relation relation, Buffer buffer, TransactionId OldestXmin)
9394
/*
9495
* Now that we have buffer lock, get accurate information about the
9596
* page's free space, and recheck the heuristic about whether to prune.
97+
* (We needn't recheck PageIsPrunable, since no one else could have
98+
* pruned while we hold pin.)
9699
*/
97100
if (PageIsFull(dp) || PageGetHeapFreeSpace((Page) dp) < minfree)
98101
{
@@ -147,7 +150,7 @@ heap_page_prune(Relation relation, Buffer buffer, TransactionId OldestXmin,
147150
START_CRIT_SECTION();
148151

149152
/*
150-
* Mark the page as clear of prunable tuples. If we find a tuple which
153+
* Mark the page as clear of prunable tuples. If we find a tuple which
151154
* may soon become prunable, we shall set the hint again. Also clear
152155
* the "page is full" flag, since there's no point in repeating the
153156
* prune/defrag process until something else happens to the page.
@@ -203,6 +206,14 @@ heap_page_prune(Relation relation, Buffer buffer, TransactionId OldestXmin,
203206
PageSetLSN(BufferGetPage(buffer), recptr);
204207
}
205208
}
209+
else
210+
{
211+
/*
212+
* If we didn't prune anything, we have nonetheless updated the
213+
* pd_prune_xid field; treat this as a non-WAL-logged hint.
214+
*/
215+
SetBufferCommitInfoNeedsSave(buffer);
216+
}
206217

207218
END_CRIT_SECTION();
208219

@@ -392,18 +403,18 @@ heap_prune_chain(Relation relation, Buffer buffer, OffsetNumber rootoffnum,
392403
case HEAPTUPLE_RECENTLY_DEAD:
393404
recent_dead = true;
394405
/*
395-
* This tuple may soon become DEAD. Re-set the hint bit so
406+
* This tuple may soon become DEAD. Update the hint field so
396407
* that the page is reconsidered for pruning in future.
397408
*/
398-
PageSetPrunable(dp);
409+
PageSetPrunable(dp, HeapTupleHeaderGetXmax(htup));
399410
break;
400411

401412
case HEAPTUPLE_DELETE_IN_PROGRESS:
402413
/*
403-
* This tuple may soon become DEAD. Re-set the hint bit so
414+
* This tuple may soon become DEAD. Update the hint field so
404415
* that the page is reconsidered for pruning in future.
405416
*/
406-
PageSetPrunable(dp);
417+
PageSetPrunable(dp, HeapTupleHeaderGetXmax(htup));
407418
break;
408419

409420
case HEAPTUPLE_LIVE:

src/backend/storage/page/bufpage.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/storage/page/bufpage.c,v 1.74 2007/09/20 17:56:31 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/storage/page/bufpage.c,v 1.75 2007/09/21 21:25:42 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -40,11 +40,12 @@ PageInit(Page page, Size pageSize, Size specialSize)
4040
/* Make sure all fields of page are zero, as well as unused space */
4141
MemSet(p, 0, pageSize);
4242

43-
/* p->pd_flags = 0; done by above MemSet */
43+
/* p->pd_flags = 0; done by above MemSet */
4444
p->pd_lower = SizeOfPageHeaderData;
4545
p->pd_upper = pageSize - specialSize;
4646
p->pd_special = pageSize - specialSize;
4747
PageSetPageSizeAndVersion(page, pageSize, PG_PAGE_LAYOUT_VERSION);
48+
/* p->pd_prune_xid = InvalidTransactionId; done by above MemSet */
4849
}
4950

5051

src/include/catalog/catversion.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
3838
* Portions Copyright (c) 1994, Regents of the University of California
3939
*
40-
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.426 2007/09/20 17:56:32 tgl Exp $
40+
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.427 2007/09/21 21:25:42 tgl Exp $
4141
*
4242
*-------------------------------------------------------------------------
4343
*/
@@ -53,6 +53,6 @@
5353
*/
5454

5555
/* yyyymmddN */
56-
#define CATALOG_VERSION_NO 200709201
56+
#define CATALOG_VERSION_NO 200709211
5757

5858
#endif

0 commit comments

Comments
 (0)