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

Commited1b1ee

Browse files
committed
Optimize pg_visibility with read streams.
We've measured 5% performance improvement, and this arranges to benefitautomatically from future optimizations to the read_stream subsystem.Nazir Bilal YavuzDiscussion:https://postgr.es/m/CAN55FZ1_Ru3XpMgTwsU67FTH2fs_FrRROmb7x6zs+F44QBEiww@mail.gmail.com
1 parentc582b75 commited1b1ee

File tree

1 file changed

+93
-21
lines changed

1 file changed

+93
-21
lines changed

‎contrib/pg_visibility/pg_visibility.c

Lines changed: 93 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include"storage/bufmgr.h"
2222
#include"storage/proc.h"
2323
#include"storage/procarray.h"
24+
#include"storage/read_stream.h"
2425
#include"storage/smgr.h"
2526
#include"utils/rel.h"
2627
#include"utils/snapmgr.h"
@@ -41,6 +42,17 @@ typedef struct corrupt_items
4142
ItemPointertids;
4243
}corrupt_items;
4344

45+
/* for collect_corrupt_items_read_stream_next_block */
46+
structcollect_corrupt_items_read_stream_private
47+
{
48+
boolall_frozen;
49+
boolall_visible;
50+
BlockNumbercurrent_blocknum;
51+
BlockNumberlast_exclusive;
52+
Relationrel;
53+
Buffervmbuffer;
54+
};
55+
4456
PG_FUNCTION_INFO_V1(pg_visibility_map);
4557
PG_FUNCTION_INFO_V1(pg_visibility_map_rel);
4658
PG_FUNCTION_INFO_V1(pg_visibility);
@@ -478,6 +490,7 @@ collect_visibility_data(Oid relid, bool include_pd)
478490
BlockNumberblkno;
479491
Buffervmbuffer=InvalidBuffer;
480492
BufferAccessStrategybstrategy=GetAccessStrategy(BAS_BULKREAD);
493+
ReadStream*stream=NULL;
481494

482495
rel=relation_open(relid,AccessShareLock);
483496

@@ -489,6 +502,22 @@ collect_visibility_data(Oid relid, bool include_pd)
489502
info->next=0;
490503
info->count=nblocks;
491504

505+
/* Create a stream if reading main fork. */
506+
if (include_pd)
507+
{
508+
BlockRangeReadStreamPrivatep;
509+
510+
p.current_blocknum=0;
511+
p.last_exclusive=nblocks;
512+
stream=read_stream_begin_relation(READ_STREAM_FULL,
513+
bstrategy,
514+
rel,
515+
MAIN_FORKNUM,
516+
block_range_read_stream_cb,
517+
&p,
518+
0);
519+
}
520+
492521
for (blkno=0;blkno<nblocks;++blkno)
493522
{
494523
int32mapbits;
@@ -513,8 +542,7 @@ collect_visibility_data(Oid relid, bool include_pd)
513542
Bufferbuffer;
514543
Pagepage;
515544

516-
buffer=ReadBufferExtended(rel,MAIN_FORKNUM,blkno,RBM_NORMAL,
517-
bstrategy);
545+
buffer=read_stream_next_buffer(stream,NULL);
518546
LockBuffer(buffer,BUFFER_LOCK_SHARE);
519547

520548
page=BufferGetPage(buffer);
@@ -525,6 +553,12 @@ collect_visibility_data(Oid relid, bool include_pd)
525553
}
526554
}
527555

556+
if (include_pd)
557+
{
558+
Assert(read_stream_next_buffer(stream,NULL)==InvalidBuffer);
559+
read_stream_end(stream);
560+
}
561+
528562
/* Clean up. */
529563
if (vmbuffer!=InvalidBuffer)
530564
ReleaseBuffer(vmbuffer);
@@ -610,6 +644,38 @@ GetStrictOldestNonRemovableTransactionId(Relation rel)
610644
}
611645
}
612646

647+
/*
648+
* Callback function to get next block for read stream object used in
649+
* collect_corrupt_items() function.
650+
*/
651+
staticBlockNumber
652+
collect_corrupt_items_read_stream_next_block(ReadStream*stream,
653+
void*callback_private_data,
654+
void*per_buffer_data)
655+
{
656+
structcollect_corrupt_items_read_stream_private*p=callback_private_data;
657+
658+
for (;p->current_blocknum<p->last_exclusive;p->current_blocknum++)
659+
{
660+
boolcheck_frozen= false;
661+
boolcheck_visible= false;
662+
663+
/* Make sure we are interruptible. */
664+
CHECK_FOR_INTERRUPTS();
665+
666+
if (p->all_frozen&&VM_ALL_FROZEN(p->rel,p->current_blocknum,&p->vmbuffer))
667+
check_frozen= true;
668+
if (p->all_visible&&VM_ALL_VISIBLE(p->rel,p->current_blocknum,&p->vmbuffer))
669+
check_visible= true;
670+
if (!check_visible&& !check_frozen)
671+
continue;
672+
673+
returnp->current_blocknum++;
674+
}
675+
676+
returnInvalidBlockNumber;
677+
}
678+
613679
/*
614680
* Returns a list of items whose visibility map information does not match
615681
* the status of the tuples on the page.
@@ -628,12 +694,13 @@ static corrupt_items *
628694
collect_corrupt_items(Oidrelid,boolall_visible,boolall_frozen)
629695
{
630696
Relationrel;
631-
BlockNumbernblocks;
632697
corrupt_items*items;
633-
BlockNumberblkno;
634698
Buffervmbuffer=InvalidBuffer;
635699
BufferAccessStrategybstrategy=GetAccessStrategy(BAS_BULKREAD);
636700
TransactionIdOldestXmin=InvalidTransactionId;
701+
structcollect_corrupt_items_read_stream_privatep;
702+
ReadStream*stream;
703+
Bufferbuffer;
637704

638705
rel=relation_open(relid,AccessShareLock);
639706

@@ -643,8 +710,6 @@ collect_corrupt_items(Oid relid, bool all_visible, bool all_frozen)
643710
if (all_visible)
644711
OldestXmin=GetStrictOldestNonRemovableTransactionId(rel);
645712

646-
nblocks=RelationGetNumberOfBlocks(rel);
647-
648713
/*
649714
* Guess an initial array size. We don't expect many corrupted tuples, so
650715
* start with a small array. This function uses the "next" field to track
@@ -658,42 +723,46 @@ collect_corrupt_items(Oid relid, bool all_visible, bool all_frozen)
658723
items->count=64;
659724
items->tids=palloc(items->count*sizeof(ItemPointerData));
660725

726+
p.current_blocknum=0;
727+
p.last_exclusive=RelationGetNumberOfBlocks(rel);
728+
p.rel=rel;
729+
p.vmbuffer=InvalidBuffer;
730+
p.all_frozen=all_frozen;
731+
p.all_visible=all_visible;
732+
stream=read_stream_begin_relation(READ_STREAM_FULL,
733+
bstrategy,
734+
rel,
735+
MAIN_FORKNUM,
736+
collect_corrupt_items_read_stream_next_block,
737+
&p,
738+
0);
739+
661740
/* Loop over every block in the relation. */
662-
for (blkno=0;blkno<nblocks;++blkno)
741+
while ((buffer=read_stream_next_buffer(stream,NULL))!=InvalidBuffer)
663742
{
664743
boolcheck_frozen= false;
665744
boolcheck_visible= false;
666-
Bufferbuffer;
667745
Pagepage;
668746
OffsetNumberoffnum,
669747
maxoff;
748+
BlockNumberblkno;
670749

671750
/* Make sure we are interruptible. */
672751
CHECK_FOR_INTERRUPTS();
673752

674-
/* Use the visibility map to decide whether to check this page. */
675-
if (all_frozen&&VM_ALL_FROZEN(rel,blkno,&vmbuffer))
676-
check_frozen= true;
677-
if (all_visible&&VM_ALL_VISIBLE(rel,blkno,&vmbuffer))
678-
check_visible= true;
679-
if (!check_visible&& !check_frozen)
680-
continue;
681-
682-
/* Read and lock the page. */
683-
buffer=ReadBufferExtended(rel,MAIN_FORKNUM,blkno,RBM_NORMAL,
684-
bstrategy);
685753
LockBuffer(buffer,BUFFER_LOCK_SHARE);
686754

687755
page=BufferGetPage(buffer);
688756
maxoff=PageGetMaxOffsetNumber(page);
757+
blkno=BufferGetBlockNumber(buffer);
689758

690759
/*
691760
* The visibility map bits might have changed while we were acquiring
692761
* the page lock. Recheck to avoid returning spurious results.
693762
*/
694-
if (check_frozen&& !VM_ALL_FROZEN(rel,blkno,&vmbuffer))
763+
if (all_frozen&& !VM_ALL_FROZEN(rel,blkno,&vmbuffer))
695764
check_frozen= false;
696-
if (check_visible&& !VM_ALL_VISIBLE(rel,blkno,&vmbuffer))
765+
if (all_visible&& !VM_ALL_VISIBLE(rel,blkno,&vmbuffer))
697766
check_visible= false;
698767
if (!check_visible&& !check_frozen)
699768
{
@@ -778,10 +847,13 @@ collect_corrupt_items(Oid relid, bool all_visible, bool all_frozen)
778847

779848
UnlockReleaseBuffer(buffer);
780849
}
850+
read_stream_end(stream);
781851

782852
/* Clean up. */
783853
if (vmbuffer!=InvalidBuffer)
784854
ReleaseBuffer(vmbuffer);
855+
if (p.vmbuffer!=InvalidBuffer)
856+
ReleaseBuffer(p.vmbuffer);
785857
relation_close(rel,AccessShareLock);
786858

787859
/*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp