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

Commit bea449c

Browse files
author
Amit Kapila
committed
Optimize DropRelFileNodesAllBuffers() for recovery.
Similar to commit d6ad34f, this patch optimizes DropRelFileNodesAllBuffers() by avoiding the complete buffer pool scan and instead find the buffers to be invalidated by doing lookups in the BufMapping table. This optimization helps operations where the relation files need to be removed like Truncate, Drop, Abort of Create Table, etc. Author: Kirk Jamison Reviewed-by: Kyotaro Horiguchi, Takayuki Tsunakawa, and Amit Kapila Tested-By: Haiying Tang Discussion: https://postgr.es/m/OSBPR01MB3207DCA7EC725FDD661B3EDAEF660@OSBPR01MB3207.jpnprd01.prod.outlook.com
1 parent fce7d0e commit bea449c

File tree

3 files changed

+84
-16
lines changed

3 files changed

+84
-16
lines changed

src/backend/storage/buffer/bufmgr.c

+77-9
Original file line numberDiff line numberDiff line change
@@ -3104,28 +3104,33 @@ DropRelFileNodeBuffers(SMgrRelation smgr_reln, ForkNumber *forkNum,
31043104
* --------------------------------------------------------------------
31053105
*/
31063106
void
3107-
DropRelFileNodesAllBuffers(RelFileNodeBackend *rnodes, int nnodes)
3107+
DropRelFileNodesAllBuffers(SMgrRelation *smgr_reln, int nnodes)
31083108
{
3109-
int i,
3110-
n = 0;
3109+
int i;
3110+
int j;
3111+
int n = 0;
3112+
SMgrRelation *rels;
3113+
BlockNumber (*block)[MAX_FORKNUM + 1];
3114+
BlockNumber nBlocksToInvalidate = 0;
31113115
RelFileNode *nodes;
3116+
bool cached = true;
31123117
bool use_bsearch;
31133118

31143119
if (nnodes == 0)
31153120
return;
31163121

3117-
nodes = palloc(sizeof(RelFileNode) * nnodes); /* non-local relations */
3122+
rels = palloc(sizeof(SMgrRelation) * nnodes); /* non-local relations */
31183123

31193124
/* If it's a local relation, it's localbuf.c's problem. */
31203125
for (i = 0; i < nnodes; i++)
31213126
{
3122-
if (RelFileNodeBackendIsTemp(rnodes[i]))
3127+
if (RelFileNodeBackendIsTemp(smgr_reln[i]->smgr_rnode))
31233128
{
3124-
if (rnodes[i].backend == MyBackendId)
3125-
DropRelFileNodeAllLocalBuffers(rnodes[i].node);
3129+
if (smgr_reln[i]->smgr_rnode.backend == MyBackendId)
3130+
DropRelFileNodeAllLocalBuffers(smgr_reln[i]->smgr_rnode.node);
31263131
}
31273132
else
3128-
nodes[n++] = rnodes[i].node;
3133+
rels[n++] = smgr_reln[i];
31293134
}
31303135

31313136
/*
@@ -3134,10 +3139,72 @@ DropRelFileNodesAllBuffers(RelFileNodeBackend *rnodes, int nnodes)
31343139
*/
31353140
if (n == 0)
31363141
{
3137-
pfree(nodes);
3142+
pfree(rels);
31383143
return;
31393144
}
31403145

3146+
/*
3147+
* This is used to remember the number of blocks for all the relations
3148+
* forks.
3149+
*/
3150+
block = (BlockNumber (*)[MAX_FORKNUM + 1])
3151+
palloc(sizeof(BlockNumber) * n * (MAX_FORKNUM + 1));
3152+
3153+
/*
3154+
* We can avoid scanning the entire buffer pool if we know the exact size
3155+
* of each of the given relation forks. See DropRelFileNodeBuffers.
3156+
*/
3157+
for (i = 0; i < n && cached; i++)
3158+
{
3159+
for (j = 0; j <= MAX_FORKNUM; j++)
3160+
{
3161+
/* Get the number of blocks for a relation's fork. */
3162+
block[i][j] = smgrnblocks_cached(rels[i], j);
3163+
3164+
/* We need to only consider the relation forks that exists. */
3165+
if (block[i][j] == InvalidBlockNumber)
3166+
{
3167+
if (!smgrexists(rels[i], j))
3168+
continue;
3169+
cached = false;
3170+
break;
3171+
}
3172+
3173+
/* calculate the total number of blocks to be invalidated */
3174+
nBlocksToInvalidate += block[i][j];
3175+
}
3176+
}
3177+
3178+
/*
3179+
* We apply the optimization iff the total number of blocks to invalidate
3180+
* is below the BUF_DROP_FULL_SCAN_THRESHOLD.
3181+
*/
3182+
if (cached && nBlocksToInvalidate < BUF_DROP_FULL_SCAN_THRESHOLD)
3183+
{
3184+
for (i = 0; i < n; i++)
3185+
{
3186+
for (j = 0; j <= MAX_FORKNUM; j++)
3187+
{
3188+
/* ignore relation forks that doesn't exist */
3189+
if (!BlockNumberIsValid(block[i][j]))
3190+
continue;
3191+
3192+
/* drop all the buffers for a particular relation fork */
3193+
FindAndDropRelFileNodeBuffers(rels[i]->smgr_rnode.node,
3194+
j, block[i][j], 0);
3195+
}
3196+
}
3197+
3198+
pfree(block);
3199+
pfree(rels);
3200+
return;
3201+
}
3202+
3203+
pfree(block);
3204+
nodes = palloc(sizeof(RelFileNode) * n); /* non-local relations */
3205+
for (i = 0; i < n; i++)
3206+
nodes[i] = rels[i]->smgr_rnode.node;
3207+
31413208
/*
31423209
* For low number of relations to drop just use a simple walk through, to
31433210
* save the bsearch overhead. The threshold to use is rather a guess than
@@ -3193,6 +3260,7 @@ DropRelFileNodesAllBuffers(RelFileNodeBackend *rnodes, int nnodes)
31933260
}
31943261

31953262
pfree(nodes);
3263+
pfree(rels);
31963264
}
31973265

31983266
/* ---------------------------------------------------------------------

src/backend/storage/smgr/smgr.c

+6-6
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,12 @@ smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo)
390390
if (nrels == 0)
391391
return;
392392

393+
/*
394+
* Get rid of any remaining buffers for the relations. bufmgr will just
395+
* drop them without bothering to write the contents.
396+
*/
397+
DropRelFileNodesAllBuffers(rels, nrels);
398+
393399
/*
394400
* create an array which contains all relations to be dropped, and close
395401
* each relation's forks at the smgr level while at it
@@ -407,12 +413,6 @@ smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo)
407413
smgrsw[which].smgr_close(rels[i], forknum);
408414
}
409415

410-
/*
411-
* Get rid of any remaining buffers for the relations. bufmgr will just
412-
* drop them without bothering to write the contents.
413-
*/
414-
DropRelFileNodesAllBuffers(rnodes, nrels);
415-
416416
/*
417417
* It'd be nice to tell the stats collector to forget them immediately,
418418
* too. But we can't because we don't know the OIDs.

src/include/storage/bufmgr.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ extern void FlushRelationsAllBuffers(struct SMgrRelationData **smgrs, int nrels)
205205
extern void FlushDatabaseBuffers(Oid dbid);
206206
extern void DropRelFileNodeBuffers(struct SMgrRelationData *smgr_reln, ForkNumber *forkNum,
207207
int nforks, BlockNumber *firstDelBlock);
208-
extern void DropRelFileNodesAllBuffers(RelFileNodeBackend *rnodes, int nnodes);
208+
extern void DropRelFileNodesAllBuffers(struct SMgrRelationData **smgr_reln, int nnodes);
209209
extern void DropDatabaseBuffers(Oid dbid);
210210

211211
#define RelationGetNumberOfBlocks(reln) \

0 commit comments

Comments
 (0)