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

Commit159f8c6

Browse files
committed
From: Dan McGuirk <mcguirk@indirect.com>
Reply-To: hackers@hub.org, Dan McGuirk <mcguirk@indirect.com>To: hackers@hub.orgSubject: [HACKERS] tmin writeback optimizationI was doing some profiling of the backend, and noticed that during a certainbenchmark I was running somewhere between 30% and 75% of the backend's CPUtime was being spent in calls to TransactionIdDidCommit() fromHeapTupleSatisfiesNow() or HeapTupleSatisfiesItself() to determine thatchanged rows' transactions had in fact been committed even though the rows'tmin values had not yet been set.When a query looks at a given row, it needs to figure out whether thetransaction that changed the row has been committed and hence it should payattention to the row, or whether on the other hand the transaction is stillin progress or has been aborted and hence the row should be ignored. Ifa tmin value is set, it is known definitively that the row's transactionhas been committed. However, if tmin is not set, the transactionreferred to in xmin must be looked up in pg_log, and this is what thebackend was spending a lot of time doing during my benchmark.So, implementing a method suggested by Vadim, I created the followingpatch that, the first time a query finds a committed row whose tmin valueis not set, sets it, and marks the buffer where the row is stored asdirty. (It works for tmax, too.) This doesn't result in the boost inreal time performance I was hoping for, however it does decrease backendCPU usage by up to two-thirds in certain situations, so it could berather beneficial in high-concurrency settings.
1 parentd98f72e commit159f8c6

File tree

8 files changed

+110
-34
lines changed

8 files changed

+110
-34
lines changed

‎src/backend/access/common/heapvalid.c

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/access/common/Attic/heapvalid.c,v 1.12 1996/11/10 02:56:47 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/access/common/Attic/heapvalid.c,v 1.13 1997/03/28 07:03:53 scrappy Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -21,6 +21,7 @@
2121
#include<storage/bufpage.h>
2222
#include<utils/rel.h>
2323
#include<utils/tqual.h>
24+
#include<storage/bufmgr.h>
2425

2526
/* ----------------
2627
*heap_keytest
@@ -89,14 +90,16 @@ heap_keytest(HeapTuple t,
8990
HeapTuple
9091
heap_tuple_satisfies(ItemIditemId,
9192
Relationrelation,
93+
Bufferbuffer,
9294
PageHeaderdisk_page,
9395
TimeQualqual,
9496
intnKeys,
9597
ScanKeykey)
9698
{
97-
HeapTupletuple;
99+
HeapTupletuple,result;
98100
boolres;
99-
101+
TransactionIdold_tmin,old_tmax;
102+
100103
if (!ItemIdIsUsed(itemId))
101104
returnNULL;
102105

@@ -107,12 +110,26 @@ heap_tuple_satisfies(ItemId itemId,
107110
nKeys,key);
108111
else
109112
res= TRUE;
110-
111-
if (res&& (relation->rd_rel->relkind==RELKIND_UNCATALOGED
112-
||HeapTupleSatisfiesTimeQual(tuple,qual)))
113-
returntuple;
114-
115-
return (HeapTuple)NULL;
113+
114+
result= (HeapTuple)NULL;
115+
if (res) {
116+
if(relation->rd_rel->relkind==RELKIND_UNCATALOGED) {
117+
result=tuple;
118+
}else {
119+
old_tmin=tuple->t_tmin;
120+
old_tmax=tuple->t_tmax;
121+
res=HeapTupleSatisfiesTimeQual(tuple,qual);
122+
if(tuple->t_tmin!=old_tmin||
123+
tuple->t_tmax!=old_tmax) {
124+
SetBufferCommitInfoNeedsSave(buffer);
125+
}
126+
if(res) {
127+
result=tuple;
128+
}
129+
}
130+
}
131+
132+
returnresult;
116133
}
117134

118135
/*

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.10 1997/01/23 05:59:47 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.11 1997/03/28 07:04:11 scrappy Exp $
1111
*
1212
*
1313
* INTERFACE ROUTINES
@@ -388,7 +388,7 @@ heapgettup(Relation relation,
388388
*if current tuple qualifies, return it.
389389
* ----------------
390390
*/
391-
if ((rtup=heap_tuple_satisfies(lpp,relation, (PageHeader)dp,
391+
if ((rtup=heap_tuple_satisfies(lpp,relation,*b,(PageHeader)dp,
392392
timeQual,nkeys,key))!=NULL) {
393393
ItemPointeriptr=&(rtup->t_ctid);
394394
if (ItemPointerGetBlockNumber(iptr)!=page) {
@@ -1009,7 +1009,7 @@ heap_fetch(Relation relation,
10091009
* ----------------
10101010
*/
10111011

1012-
tuple=heap_tuple_satisfies(lp,relation,dp,
1012+
tuple=heap_tuple_satisfies(lp,relation,buffer,dp,
10131013
timeQual,0,(ScanKey)NULL);
10141014

10151015
if (tuple==NULL)
@@ -1154,7 +1154,7 @@ heap_delete(Relation relation, ItemPointer tid)
11541154
*check that we're deleteing a valid item
11551155
* ----------------
11561156
*/
1157-
if (!(tp=heap_tuple_satisfies(lp,relation,dp,
1157+
if (!(tp=heap_tuple_satisfies(lp,relation,b,dp,
11581158
NowTimeQual,0, (ScanKey)NULL))) {
11591159

11601160
/* XXX call something else */
@@ -1282,6 +1282,7 @@ heap_replace(Relation relation, ItemPointer otid, HeapTuple tup)
12821282
*/
12831283
if (!heap_tuple_satisfies(lp,
12841284
relation,
1285+
buffer,
12851286
(PageHeader)dp,
12861287
NowTimeQual,
12871288
0,

‎src/backend/storage/buffer/buf_init.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.7 1997/01/26 00:45:25 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.8 1997/03/28 07:04:52 scrappy Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -64,6 +64,8 @@ extern IpcSemaphoreId WaitIOSemId;
6464

6565
long*PrivateRefCount;/* also used in freelist.c */
6666
long*LastRefCount;/* refcounts of last ExecMain level */
67+
long*CommitInfoNeedsSave;/* to write buffers where we have filled in */
68+
/* t_tmin (or t_tmax) */
6769

6870
/*
6971
* Data Structures:
@@ -236,6 +238,7 @@ InitBufferPool(IPCKey key)
236238
#endif
237239
PrivateRefCount= (long*)calloc(NBuffers,sizeof(long));
238240
LastRefCount= (long*)calloc(NBuffers,sizeof(long));
241+
CommitInfoNeedsSave= (long*)calloc(NBuffers,sizeof(long));
239242
}
240243

241244
/* -----------------------------------------------------

‎src/backend/storage/buffer/bufmgr.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.10 1997/01/23 19:43:23 scrappy Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.11 1997/03/28 07:05:03 scrappy Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -848,6 +848,10 @@ ReleaseAndReadBuffer(Buffer buffer,
848848
AddBufferToFreelist(bufHdr);
849849
bufHdr->flags |=BM_FREE;
850850
}
851+
if(CommitInfoNeedsSave[buffer-1]) {
852+
bufHdr->flags |= (BM_DIRTY |BM_JUST_DIRTIED);
853+
CommitInfoNeedsSave[buffer-1]=0;
854+
}
851855
retbuf=ReadBufferWithBufferLock(relation,blockNum, true);
852856
returnretbuf;
853857
}
@@ -1083,6 +1087,7 @@ ResetBufferPool()
10831087
{
10841088
registerinti;
10851089
for (i=1;i<=NBuffers;i++) {
1090+
CommitInfoNeedsSave[i-1]=0;
10861091
if (BufferIsValid(i)) {
10871092
while(PrivateRefCount[i-1]>0) {
10881093
ReleaseBuffer(i);
@@ -1498,6 +1503,10 @@ ReleaseBuffer(Buffer buffer)
14981503
AddBufferToFreelist(bufHdr);
14991504
bufHdr->flags |=BM_FREE;
15001505
}
1506+
if(CommitInfoNeedsSave[buffer-1]) {
1507+
bufHdr->flags |= (BM_DIRTY |BM_JUST_DIRTIED);
1508+
CommitInfoNeedsSave[buffer-1]=0;
1509+
}
15011510
SpinRelease(BufMgrLock);
15021511
}
15031512

@@ -1734,3 +1743,8 @@ int SetBufferWriteMode (int mode)
17341743
WriteMode=mode;
17351744
return (old);
17361745
}
1746+
1747+
voidSetBufferCommitInfoNeedsSave(Bufferbuffer)
1748+
{
1749+
CommitInfoNeedsSave[buffer-1]++;
1750+
}

‎src/backend/utils/time/tqual.c

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.1.1.1 1996/07/09 06:22:10 scrappy Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.2 1997/03/28 07:05:28 scrappy Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -478,18 +478,24 @@ HeapTupleSatisfiesTimeQual(HeapTuple tuple, TimeQual qual)
478478
/*
479479
* HeapTupleSatisfiesItself --
480480
*True iff heap tuple is valid for "itself."
481+
* "{it}self" means valid as of everything that's happened
482+
* in the current transaction, _including_ the current command.
481483
*
482484
* Note:
483485
*Assumes heap tuple is valid.
484486
*/
485487
/*
486488
* The satisfaction of "itself" requires the following:
487489
*
488-
* ((Xmin == my-transaction && (Xmax is null [|| Xmax != my-transaction)])
490+
* ((Xmin == my-transaction && the row was updated by the current transaction, and
491+
* (Xmax is null it was not deleted
492+
* [|| Xmax != my-transaction)]) [or it was deleted by another transaction]
489493
* ||
490494
*
491-
* (Xmin is committed &&
492-
*(Xmax is null || (Xmax != my-transaction && Xmax is not committed)))
495+
* (Xmin is committed && the row was modified by a committed transaction, and
496+
*(Xmax is null || the row has not been deleted, or
497+
* (Xmax != my-transaction && the row was deleted by another transaction
498+
* Xmax is not committed))) that has not been committed
493499
*/
494500
staticbool
495501
HeapTupleSatisfiesItself(HeapTupletuple)
@@ -508,6 +514,8 @@ HeapTupleSatisfiesItself(HeapTuple tuple)
508514
if (!TransactionIdDidCommit((TransactionId)tuple->t_xmin)) {
509515
return (false);
510516
}
517+
518+
tuple->t_tmin=TransactionIdGetCommitTime(tuple->t_xmin);
511519
}
512520
/* the tuple was inserted validly */
513521

@@ -522,27 +530,43 @@ HeapTupleSatisfiesItself(HeapTuple tuple)
522530
if (TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmax)) {
523531
return (false);
524532
}
533+
534+
if (!TransactionIdDidCommit((TransactionId)tuple->t_xmax)) {
535+
return (true);
536+
}
525537

526-
return ((bool)!TransactionIdDidCommit((TransactionId)tuple->t_xmax));
538+
/* by here, deleting transaction has committed */
539+
tuple->t_tmax=TransactionIdGetCommitTime(tuple->t_xmax);
540+
541+
return (false);
527542
}
528543

529544
/*
530545
* HeapTupleSatisfiesNow --
531546
*True iff heap tuple is valid "now."
547+
* "now" means valid including everything that's happened
548+
* in the current transaction _up to, but not including,_
549+
* the current command.
532550
*
533551
* Note:
534552
*Assumes heap tuple is valid.
535553
*/
536554
/*
537555
* The satisfaction of "now" requires the following:
538556
*
539-
* ((Xmin == my-transaction && Cmin != my-command &&
540-
*(Xmax is null || (Xmax == my-transaction && Cmax != my-command)))
541-
* ||
557+
* ((Xmin == my-transaction && changed by the current transaction
558+
* Cmin != my-command && but not by this command, and
559+
* (Xmax is null || the row has not been deleted, or
560+
* (Xmax == my-transaction && it was deleted by the current transaction
561+
* Cmax != my-command))) but not by this command,
562+
* || or
542563
*
543-
* (Xmin is committed &&
544-
*(Xmax is null || (Xmax == my-transaction && Cmax == my-command) ||
545-
*(Xmax is not committed && Xmax != my-transaction))))
564+
* (Xmin is committed && the row was modified by a committed transaction, and
565+
* (Xmax is null || the row has not been deleted, or
566+
* (Xmax == my-transaction && the row is being deleted by this command, or
567+
* Cmax == my-command) ||
568+
* (Xmax is not committed && the row was deleted by another transaction
569+
* Xmax != my-transaction)))) that has not been committed
546570
*
547571
*mao says 17 march 1993: the tests in this routine are correct;
548572
*if you think they're not, you're wrong, and you should think
@@ -605,6 +629,13 @@ HeapTupleSatisfiesNow(HeapTuple tuple)
605629
if (!TransactionIdDidCommit((TransactionId)tuple->t_xmin)) {
606630
return (false);
607631
}
632+
633+
/*
634+
* the transaction has been committed--store the commit time _now_
635+
* instead of waiting for a vacuum so we avoid the expensive call
636+
* next time.
637+
*/
638+
tuple->t_tmin=TransactionIdGetCommitTime(tuple->t_xmin);
608639
}
609640

610641
/* by here, the inserting transaction has committed */
@@ -615,12 +646,18 @@ HeapTupleSatisfiesNow(HeapTuple tuple)
615646
if (TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmax)) {
616647
return (false);
617648
}
618-
649+
650+
if (AbsoluteTimeIsBackwardCompatiblyReal(tuple->t_tmax)) {
651+
return (false);
652+
}
653+
619654
if (!TransactionIdDidCommit((TransactionId)tuple->t_xmax)) {
620-
return (true);
655+
return (true);
621656
}
622-
623-
/* by here, deleting transaction has committed */
657+
658+
/* xmax transaction committed, but no tmax set. so set it. */
659+
tuple->t_tmax=TransactionIdGetCommitTime(tuple->t_xmax);
660+
624661
return (false);
625662
}
626663

‎src/include/access/valid.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*
77
* Copyright (c) 1994, Regents of the University of California
88
*
9-
* $Id: valid.h,v 1.3 1996/11/05 10:37:07 scrappy Exp $
9+
* $Id: valid.h,v 1.4 1997/03/28 07:05:54 scrappy Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -26,7 +26,9 @@ extern bool heap_keytest(HeapTuple t, TupleDesc tupdesc,
2626
intnkeys,ScanKeykeys);
2727

2828
externHeapTupleheap_tuple_satisfies(ItemIditemId,Relationrelation,
29-
PageHeaderdisk_page,TimeQualqual,intnKeys,ScanKeykey);
29+
Bufferbuffer,PageHeaderdisk_page,
30+
TimeQualqual,intnKeys,
31+
ScanKeykey);
3032

3133
externboolTupleUpdatedByCurXactAndCmd(HeapTuplet);
3234

‎src/include/storage/buf_internals.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*
77
* Copyright (c) 1994, Regents of the University of California
88
*
9-
* $Id: buf_internals.h,v 1.11 1997/01/25 03:09:33 momjian Exp $
9+
* $Id: buf_internals.h,v 1.12 1997/03/28 07:06:48 scrappy Exp $
1010
*
1111
* NOTE
1212
*If BUFFERPAGE0 is defined, then 0 will be used as a
@@ -216,6 +216,7 @@ extern BufferDesc *BufferDescriptors;
216216
externBufferBlockBufferBlocks;
217217
externlong*PrivateRefCount;
218218
externlong*LastRefCount;
219+
externlong*CommitInfoNeedsSave;
219220
externSPINLOCKBufMgrLock;
220221

221222
/* localbuf.c */

‎src/include/storage/bufmgr.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*
77
* Copyright (c) 1994, Regents of the University of California
88
*
9-
* $Id: bufmgr.h,v 1.9 1997/01/16 07:53:27 vadim Exp $
9+
* $Id: bufmgr.h,v 1.10 1997/03/28 07:06:53 scrappy Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -114,6 +114,7 @@ extern int ReleaseAndReadBuffer_Debug(char *file,
114114
externvoidBufferRefCountReset(int*refcountsave);
115115
externvoidBufferRefCountRestore(int*refcountsave);
116116
externintSetBufferWriteMode (intmode);
117+
externvoidSetBufferCommitInfoNeedsSave(Bufferbuffer);
117118

118119
#endif/* !defined(BufMgrIncluded) */
119120

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp