Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit9e85743

Browse files
committed
Don't include unused space in LOG_NEWPAGE records.
This is the same trick we use when taking a full page image of a bufferpassed to XLogInsert.
1 parent22122c8 commit9e85743

File tree

11 files changed

+109
-62
lines changed

11 files changed

+109
-62
lines changed

‎src/backend/access/gin/gininsert.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -435,10 +435,10 @@ ginbuildempty(PG_FUNCTION_ARGS)
435435
START_CRIT_SECTION();
436436
GinInitMetabuffer(MetaBuffer);
437437
MarkBufferDirty(MetaBuffer);
438-
log_newpage_buffer(MetaBuffer);
438+
log_newpage_buffer(MetaBuffer, false);
439439
GinInitBuffer(RootBuffer,GIN_LEAF);
440440
MarkBufferDirty(RootBuffer);
441-
log_newpage_buffer(RootBuffer);
441+
log_newpage_buffer(RootBuffer, false);
442442
END_CRIT_SECTION();
443443

444444
/* Unlock and release the buffers. */

‎src/backend/access/gist/gist.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ gistbuildempty(PG_FUNCTION_ARGS)
8383
START_CRIT_SECTION();
8484
GISTInitBuffer(buffer,F_LEAF);
8585
MarkBufferDirty(buffer);
86-
log_newpage_buffer(buffer);
86+
log_newpage_buffer(buffer, true);
8787
END_CRIT_SECTION();
8888

8989
/* Unlock and release the buffer */

‎src/backend/access/heap/heapam.c

Lines changed: 83 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -6207,16 +6207,22 @@ log_heap_update(Relation reln, Buffer oldbuf,
62076207
* memory and writing them directly to smgr. If you're using buffers, call
62086208
* log_newpage_buffer instead.
62096209
*
6210-
* Note: the NEWPAGE log record is used for both heaps and indexes, so do
6211-
* not do anything that assumes we are touching a heap.
6210+
* If the page follows the standard page layout, with a PageHeader and unused
6211+
* space between pd_lower and pd_upper, set 'page_std' to TRUE. That allows
6212+
* the unused space to be left out from the WAL record, making it smaller.
62126213
*/
62136214
XLogRecPtr
62146215
log_newpage(RelFileNode*rnode,ForkNumberforkNum,BlockNumberblkno,
6215-
Pagepage)
6216+
Pagepage,boolpage_std)
62166217
{
62176218
xl_heap_newpagexlrec;
62186219
XLogRecPtrrecptr;
6219-
XLogRecDatardata[2];
6220+
XLogRecDatardata[3];
6221+
6222+
/*
6223+
* Note: the NEWPAGE log record is used for both heaps and indexes, so do
6224+
* not do anything that assumes we are touching a heap.
6225+
*/
62206226

62216227
/* NO ELOG(ERROR) from here till newpage op is logged */
62226228
START_CRIT_SECTION();
@@ -6225,15 +6231,58 @@ log_newpage(RelFileNode *rnode, ForkNumber forkNum, BlockNumber blkno,
62256231
xlrec.forknum=forkNum;
62266232
xlrec.blkno=blkno;
62276233

6234+
if (page_std)
6235+
{
6236+
/* Assume we can omit data between pd_lower and pd_upper */
6237+
uint16lower= ((PageHeader)page)->pd_lower;
6238+
uint16upper= ((PageHeader)page)->pd_upper;
6239+
6240+
if (lower >=SizeOfPageHeaderData&&
6241+
upper>lower&&
6242+
upper <=BLCKSZ)
6243+
{
6244+
xlrec.hole_offset=lower;
6245+
xlrec.hole_length=upper-lower;
6246+
}
6247+
else
6248+
{
6249+
/* No "hole" to compress out */
6250+
xlrec.hole_offset=0;
6251+
xlrec.hole_length=0;
6252+
}
6253+
}
6254+
else
6255+
{
6256+
/* Not a standard page header, don't try to eliminate "hole" */
6257+
xlrec.hole_offset=0;
6258+
xlrec.hole_length=0;
6259+
}
6260+
62286261
rdata[0].data= (char*)&xlrec;
62296262
rdata[0].len=SizeOfHeapNewpage;
62306263
rdata[0].buffer=InvalidBuffer;
62316264
rdata[0].next=&(rdata[1]);
62326265

6233-
rdata[1].data= (char*)page;
6234-
rdata[1].len=BLCKSZ;
6235-
rdata[1].buffer=InvalidBuffer;
6236-
rdata[1].next=NULL;
6266+
if (xlrec.hole_length==0)
6267+
{
6268+
rdata[1].data= (char*)page;
6269+
rdata[1].len=BLCKSZ;
6270+
rdata[1].buffer=InvalidBuffer;
6271+
rdata[1].next=NULL;
6272+
}
6273+
else
6274+
{
6275+
/* must skip the hole */
6276+
rdata[1].data= (char*)page;
6277+
rdata[1].len=xlrec.hole_offset;
6278+
rdata[1].buffer=InvalidBuffer;
6279+
rdata[1].next=&rdata[2];
6280+
6281+
rdata[2].data= (char*)page+ (xlrec.hole_offset+xlrec.hole_length);
6282+
rdata[2].len=BLCKSZ- (xlrec.hole_offset+xlrec.hole_length);
6283+
rdata[2].buffer=InvalidBuffer;
6284+
rdata[2].next=NULL;
6285+
}
62376286

62386287
recptr=XLogInsert(RM_HEAP_ID,XLOG_HEAP_NEWPAGE,rdata);
62396288

@@ -6257,44 +6306,24 @@ log_newpage(RelFileNode *rnode, ForkNumber forkNum, BlockNumber blkno,
62576306
* Caller should initialize the buffer and mark it dirty before calling this
62586307
* function. This function will set the page LSN and TLI.
62596308
*
6260-
* Note: the NEWPAGE log record is used for both heaps and indexes, so do
6261-
* not do anything that assumes we are touching a heap.
6309+
* If the page follows the standard page layout, with a PageHeader and unused
6310+
* space between pd_lower and pd_upper, set 'page_std' to TRUE. That allows
6311+
* the unused space to be left out from the WAL record, making it smaller.
62626312
*/
62636313
XLogRecPtr
6264-
log_newpage_buffer(Bufferbuffer)
6314+
log_newpage_buffer(Bufferbuffer,boolpage_std)
62656315
{
6266-
xl_heap_newpagexlrec;
6267-
XLogRecPtrrecptr;
6268-
XLogRecDatardata[2];
62696316
Pagepage=BufferGetPage(buffer);
6317+
RelFileNodernode;
6318+
ForkNumberforkNum;
6319+
BlockNumberblkno;
62706320

6271-
/*Weshould be in a critical section. */
6321+
/*Shared buffersshould be modified in a critical section. */
62726322
Assert(CritSectionCount>0);
62736323

6274-
BufferGetTag(buffer,&xlrec.node,&xlrec.forknum,&xlrec.blkno);
6275-
6276-
rdata[0].data= (char*)&xlrec;
6277-
rdata[0].len=SizeOfHeapNewpage;
6278-
rdata[0].buffer=InvalidBuffer;
6279-
rdata[0].next=&(rdata[1]);
6280-
6281-
rdata[1].data=page;
6282-
rdata[1].len=BLCKSZ;
6283-
rdata[1].buffer=InvalidBuffer;
6284-
rdata[1].next=NULL;
6285-
6286-
recptr=XLogInsert(RM_HEAP_ID,XLOG_HEAP_NEWPAGE,rdata);
6287-
6288-
/*
6289-
* The page may be uninitialized. If so, we can't set the LSN and TLI
6290-
* because that would corrupt the page.
6291-
*/
6292-
if (!PageIsNew(page))
6293-
{
6294-
PageSetLSN(page,recptr);
6295-
}
6324+
BufferGetTag(buffer,&rnode,&forkNum,&blkno);
62966325

6297-
returnrecptr;
6326+
returnlog_newpage(&rnode,forkNum,blkno,page,page_std);
62986327
}
62996328

63006329
/*
@@ -6582,12 +6611,15 @@ static void
65826611
heap_xlog_newpage(XLogRecPtrlsn,XLogRecord*record)
65836612
{
65846613
xl_heap_newpage*xlrec= (xl_heap_newpage*)XLogRecGetData(record);
6614+
char*blk= ((char*)xlrec)+sizeof(xl_heap_newpage);
65856615
Bufferbuffer;
65866616
Pagepage;
65876617

65886618
/* Backup blocks are not used in newpage records */
65896619
Assert(!(record->xl_info&XLR_BKP_BLOCK_MASK));
65906620

6621+
Assert(record->xl_len==SizeOfHeapNewpage+BLCKSZ-xlrec->hole_length);
6622+
65916623
/*
65926624
* Note: the NEWPAGE log record is used for both heaps and indexes, so do
65936625
* not do anything that assumes we are touching a heap.
@@ -6598,8 +6630,19 @@ heap_xlog_newpage(XLogRecPtr lsn, XLogRecord *record)
65986630
LockBuffer(buffer,BUFFER_LOCK_EXCLUSIVE);
65996631
page= (Page)BufferGetPage(buffer);
66006632

6601-
Assert(record->xl_len==SizeOfHeapNewpage+BLCKSZ);
6602-
memcpy(page, (char*)xlrec+SizeOfHeapNewpage,BLCKSZ);
6633+
if (xlrec->hole_length==0)
6634+
{
6635+
memcpy((char*)page,blk,BLCKSZ);
6636+
}
6637+
else
6638+
{
6639+
memcpy((char*)page,blk,xlrec->hole_offset);
6640+
/* must zero-fill the hole */
6641+
MemSet((char*)page+xlrec->hole_offset,0,xlrec->hole_length);
6642+
memcpy((char*)page+ (xlrec->hole_offset+xlrec->hole_length),
6643+
blk+xlrec->hole_offset,
6644+
BLCKSZ- (xlrec->hole_offset+xlrec->hole_length));
6645+
}
66036646

66046647
/*
66056648
* The page may be uninitialized. If so, we can't set the LSN because that

‎src/backend/access/heap/rewriteheap.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,8 @@ end_heap_rewrite(RewriteState state)
277277
log_newpage(&state->rs_new_rel->rd_node,
278278
MAIN_FORKNUM,
279279
state->rs_blockno,
280-
state->rs_buffer);
280+
state->rs_buffer,
281+
true);
281282
RelationOpenSmgr(state->rs_new_rel);
282283

283284
PageSetChecksumInplace(state->rs_buffer,state->rs_blockno);
@@ -622,7 +623,8 @@ raw_heap_insert(RewriteState state, HeapTuple tup)
622623
log_newpage(&state->rs_new_rel->rd_node,
623624
MAIN_FORKNUM,
624625
state->rs_blockno,
625-
page);
626+
page,
627+
true);
626628

627629
/*
628630
* Now write the page. We say isTemp = true even if it's not a

‎src/backend/access/nbtree/nbtree.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ btbuildempty(PG_FUNCTION_ARGS)
222222
(char*)metapage, true);
223223
if (XLogIsNeeded())
224224
log_newpage(&index->rd_smgr->smgr_rnode.node,INIT_FORKNUM,
225-
BTREE_METAPAGE,metapage);
225+
BTREE_METAPAGE,metapage, false);
226226

227227
/*
228228
* An immediate sync is require even if we xlog'd the page, because the

‎src/backend/access/nbtree/nbtsort.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ _bt_blwritepage(BTWriteState *wstate, Page page, BlockNumber blkno)
274274
if (wstate->btws_use_wal)
275275
{
276276
/* We use the heap NEWPAGE record type for this */
277-
log_newpage(&wstate->index->rd_node,MAIN_FORKNUM,blkno,page);
277+
log_newpage(&wstate->index->rd_node,MAIN_FORKNUM,blkno,page, true);
278278
}
279279

280280
/*

‎src/backend/access/spgist/spginsert.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ spgbuildempty(PG_FUNCTION_ARGS)
169169
(char*)page, true);
170170
if (XLogIsNeeded())
171171
log_newpage(&index->rd_smgr->smgr_rnode.node,INIT_FORKNUM,
172-
SPGIST_METAPAGE_BLKNO,page);
172+
SPGIST_METAPAGE_BLKNO,page, false);
173173

174174
/* Likewise for the root page. */
175175
SpGistInitPage(page,SPGIST_LEAF);
@@ -179,7 +179,7 @@ spgbuildempty(PG_FUNCTION_ARGS)
179179
(char*)page, true);
180180
if (XLogIsNeeded())
181181
log_newpage(&index->rd_smgr->smgr_rnode.node,INIT_FORKNUM,
182-
SPGIST_ROOT_BLKNO,page);
182+
SPGIST_ROOT_BLKNO,page, true);
183183

184184
/* Likewise for the null-tuples root page. */
185185
SpGistInitPage(page,SPGIST_LEAF |SPGIST_NULLS);
@@ -189,7 +189,7 @@ spgbuildempty(PG_FUNCTION_ARGS)
189189
(char*)page, true);
190190
if (XLogIsNeeded())
191191
log_newpage(&index->rd_smgr->smgr_rnode.node,INIT_FORKNUM,
192-
SPGIST_NULL_BLKNO,page);
192+
SPGIST_NULL_BLKNO,page, true);
193193

194194
/*
195195
* An immediate sync is required even if we xlog'd the pages, because the

‎src/backend/commands/tablecmds.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9130,9 +9130,13 @@ copy_relation_data(SMgrRelation src, SMgrRelation dst,
91309130
src->smgr_rnode.backend,
91319131
forkNum))));
91329132

9133-
/* XLOG stuff */
9133+
/*
9134+
* WAL-log the copied page. Unfortunately we don't know what kind of
9135+
* a page this is, so we have to log the full page including any
9136+
* unused space.
9137+
*/
91349138
if (use_wal)
9135-
log_newpage(&dst->smgr_rnode.node,forkNum,blkno,page);
9139+
log_newpage(&dst->smgr_rnode.node,forkNum,blkno,page, false);
91369140

91379141
PageSetChecksumInplace(page,blkno);
91389142

‎src/backend/commands/vacuumlazy.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -699,14 +699,10 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
699699
* which will cause a PANIC. To prevent that, check whether
700700
* the page has been previously WAL-logged, and if not, do that
701701
* now.
702-
*
703-
* XXX: It would be nice to use a logging method supporting
704-
* standard buffers here since log_newpage_buffer() will write
705-
* the full block instead of omitting the hole.
706702
*/
707703
if (RelationNeedsWAL(onerel)&&
708704
PageGetLSN(page)==InvalidXLogRecPtr)
709-
log_newpage_buffer(buf);
705+
log_newpage_buffer(buf, true);
710706

711707
PageSetAllVisible(page);
712708
visibilitymap_set(onerel,blkno,buf,InvalidXLogRecPtr,

‎src/include/access/heapam_xlog.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -198,10 +198,12 @@ typedef struct xl_heap_newpage
198198
RelFileNodenode;
199199
ForkNumberforknum;
200200
BlockNumberblkno;/* location of new page */
201-
/* entire page contents follow at end of record */
201+
uint16hole_offset;/* number of bytes before "hole" */
202+
uint16hole_length;/* number of bytes in "hole" */
203+
/* entire page contents (minus the hole) follow at end of record */
202204
}xl_heap_newpage;
203205

204-
#defineSizeOfHeapNewpage(offsetof(xl_heap_newpage,blkno) + sizeof(BlockNumber))
206+
#defineSizeOfHeapNewpage(offsetof(xl_heap_newpage,hole_length) + sizeof(uint16))
205207

206208
/* flags for infobits_set */
207209
#defineXLHL_XMAX_IS_MULTI0x01
@@ -282,7 +284,7 @@ extern XLogRecPtr log_heap_freeze(Relation reln, Buffer buffer,
282284
externXLogRecPtrlog_heap_visible(RelFileNodernode,Bufferheap_buffer,
283285
Buffervm_buffer,TransactionIdcutoff_xid);
284286
externXLogRecPtrlog_newpage(RelFileNode*rnode,ForkNumberforkNum,
285-
BlockNumberblk,Pagepage);
286-
externXLogRecPtrlog_newpage_buffer(Bufferbuffer);
287+
BlockNumberblk,Pagepage,boolpage_std);
288+
externXLogRecPtrlog_newpage_buffer(Bufferbuffer,boolpage_std);
287289

288290
#endif/* HEAPAM_XLOG_H */

‎src/include/access/xlog_internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ typedef struct BkpBlock
5555
/*
5656
* Each page of XLOG file has a header like this:
5757
*/
58-
#defineXLOG_PAGE_MAGIC0xD077/* can be used as WAL version indicator */
58+
#defineXLOG_PAGE_MAGIC0xD078/* can be used as WAL version indicator */
5959

6060
typedefstructXLogPageHeaderData
6161
{

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp