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

Commit6ca015f

Browse files
committed
Track unowned relations in doubly-linked list
Relations dropped in a single transaction are tracked in a list ofunowned relations. With large number of dropped relations this resultedin poor performance at the end of a transaction, when the relations areremoved from the singly linked list one by one.Commitb416691 attempted to address this issue (particularly when ithappens during recovery) by removing the relations in a reverse order,resulting in O(1) lookups in the list of unowned relations. This didnot work reliably, though, and it was possible to trigger the O(N^2)behavior in various ways.Instead of trying to remove the relations in a specific order withrespect to the linked list, which seems rather fragile, switch to aregular doubly linked. That allows us to remove relations cheaply nomatter where in the list they are.Asb416691 was a bugfix, backpatched to all supported versions, do thesame thing here.Reviewed-by: Alvaro HerreraDiscussion:https://www.postgresql.org/message-id/flat/80c27103-99e4-1d0c-642c-d9f3b94aaa0a%402ndquadrant.comBackpatch-through: 9.4
1 parent558a916 commit6ca015f

File tree

3 files changed

+20
-65
lines changed

3 files changed

+20
-65
lines changed

‎src/backend/storage/smgr/md.c

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1699,13 +1699,7 @@ DropRelationFiles(RelFileNode *delrels, int ndelrels, bool isRedo)
16991699

17001700
smgrdounlinkall(srels,ndelrels,isRedo);
17011701

1702-
/*
1703-
* Call smgrclose() in reverse order as when smgropen() is called.
1704-
* This trick enables remove_from_unowned_list() in smgrclose()
1705-
* to search the SMgrRelation from the unowned list,
1706-
* with O(1) performance.
1707-
*/
1708-
for (i=ndelrels-1;i >=0;i--)
1702+
for (i=0;i<ndelrels;i++)
17091703
smgrclose(srels[i]);
17101704
pfree(srels);
17111705
}

‎src/backend/storage/smgr/smgr.c

Lines changed: 17 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include"postgres.h"
1919

2020
#include"commands/tablespace.h"
21+
#include"lib/ilist.h"
2122
#include"storage/bufmgr.h"
2223
#include"storage/ipc.h"
2324
#include"storage/smgr.h"
@@ -97,12 +98,10 @@ static const int NSmgr = lengthof(smgrsw);
9798
*/
9899
staticHTAB*SMgrRelationHash=NULL;
99100

100-
staticSMgrRelationfirst_unowned_reln=NULL;
101+
staticdlist_headunowned_relns;
101102

102103
/* local function prototypes */
103104
staticvoidsmgrshutdown(intcode,Datumarg);
104-
staticvoidadd_to_unowned_list(SMgrRelationreln);
105-
staticvoidremove_from_unowned_list(SMgrRelationreln);
106105

107106

108107
/*
@@ -165,7 +164,7 @@ smgropen(RelFileNode rnode, BackendId backend)
165164
ctl.entrysize=sizeof(SMgrRelationData);
166165
SMgrRelationHash=hash_create("smgr relation table",400,
167166
&ctl,HASH_ELEM |HASH_BLOBS);
168-
first_unowned_reln=NULL;
167+
dlist_init(&unowned_relns);
169168
}
170169

171170
/* Look up or create an entry */
@@ -192,7 +191,7 @@ smgropen(RelFileNode rnode, BackendId backend)
192191
reln->md_num_open_segs[forknum]=0;
193192

194193
/* it has no owner yet */
195-
add_to_unowned_list(reln);
194+
dlist_push_tail(&unowned_relns,&reln->node);
196195
}
197196

198197
returnreln;
@@ -222,7 +221,7 @@ smgrsetowner(SMgrRelation *owner, SMgrRelation reln)
222221
if (reln->smgr_owner)
223222
*(reln->smgr_owner)=NULL;
224223
else
225-
remove_from_unowned_list(reln);
224+
dlist_delete(&reln->node);
226225

227226
/* Now establish the ownership relationship. */
228227
reln->smgr_owner=owner;
@@ -246,53 +245,8 @@ smgrclearowner(SMgrRelation *owner, SMgrRelation reln)
246245
/* unset our reference to the owner */
247246
reln->smgr_owner=NULL;
248247

249-
add_to_unowned_list(reln);
250-
}
251-
252-
/*
253-
* add_to_unowned_list -- link an SMgrRelation onto the unowned list
254-
*
255-
* Check remove_from_unowned_list()'s comments for performance
256-
* considerations.
257-
*/
258-
staticvoid
259-
add_to_unowned_list(SMgrRelationreln)
260-
{
261-
/* place it at head of the list (to make smgrsetowner cheap) */
262-
reln->next_unowned_reln=first_unowned_reln;
263-
first_unowned_reln=reln;
264-
}
265-
266-
/*
267-
* remove_from_unowned_list -- unlink an SMgrRelation from the unowned list
268-
*
269-
* If the reln is not present in the list, nothing happens. Typically this
270-
* would be caller error, but there seems no reason to throw an error.
271-
*
272-
* In the worst case this could be rather slow; but in all the cases that seem
273-
* likely to be performance-critical, the reln being sought will actually be
274-
* first in the list. Furthermore, the number of unowned relns touched in any
275-
* one transaction shouldn't be all that high typically. So it doesn't seem
276-
* worth expending the additional space and management logic needed for a
277-
* doubly-linked list.
278-
*/
279-
staticvoid
280-
remove_from_unowned_list(SMgrRelationreln)
281-
{
282-
SMgrRelation*link;
283-
SMgrRelationcur;
284-
285-
for (link=&first_unowned_reln,cur=*link;
286-
cur!=NULL;
287-
link=&cur->next_unowned_reln,cur=*link)
288-
{
289-
if (cur==reln)
290-
{
291-
*link=cur->next_unowned_reln;
292-
cur->next_unowned_reln=NULL;
293-
break;
294-
}
295-
}
248+
/* add to list of unowned relations */
249+
dlist_push_tail(&unowned_relns,&reln->node);
296250
}
297251

298252
/*
@@ -319,7 +273,7 @@ smgrclose(SMgrRelation reln)
319273
owner=reln->smgr_owner;
320274

321275
if (!owner)
322-
remove_from_unowned_list(reln);
276+
dlist_delete(&reln->node);
323277

324278
if (hash_search(SMgrRelationHash,
325279
(void*)&(reln->smgr_rnode),
@@ -812,13 +766,19 @@ smgrpostckpt(void)
812766
void
813767
AtEOXact_SMgr(void)
814768
{
769+
dlist_mutable_iteriter;
770+
815771
/*
816772
* Zap all unowned SMgrRelations. We rely on smgrclose() to remove each
817773
* one from the list.
818774
*/
819-
while (first_unowned_reln!=NULL)
775+
dlist_foreach_modify(iter,&unowned_relns)
820776
{
821-
Assert(first_unowned_reln->smgr_owner==NULL);
822-
smgrclose(first_unowned_reln);
777+
SMgrRelationrel=dlist_container(SMgrRelationData,node,
778+
iter.cur);
779+
780+
Assert(rel->smgr_owner==NULL);
781+
782+
smgrclose(rel);
823783
}
824784
}

‎src/include/storage/smgr.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#ifndefSMGR_H
1515
#defineSMGR_H
1616

17+
#include"lib/ilist.h"
1718
#include"storage/block.h"
1819
#include"storage/relfilenode.h"
1920

@@ -71,7 +72,7 @@ typedef struct SMgrRelationData
7172
struct_MdfdVec*md_seg_fds[MAX_FORKNUM+1];
7273

7374
/* if unowned, list link in list of all unowned SMgrRelations */
74-
structSMgrRelationData*next_unowned_reln;
75+
dlist_nodenode;
7576
}SMgrRelationData;
7677

7778
typedefSMgrRelationData*SMgrRelation;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp