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

Commitdab52ab

Browse files
committed
Improve ExecStoreTuple to be smarter about replacing the contents of
a TupleTableSlot: instead of calling ExecClearTuple, inline the neededoperations, so that we can avoid redundant steps. In particular, whenthe old and new tuples are both on the same disk page, avoid releasingand re-acquiring the buffer pin --- this saves work in both the bufmgrand ResourceOwner modules. To make this improvement actually useful,partially revert a change I made on 2004-04-21 that caused SeqNextet al to call ExecClearTuple before ExecStoreTuple. The motivationfor that, to avoid grabbing the BufMgrLock separately for releasingthe old buffer and grabbing the new one, no longer applies. Myprofiling says that this saves about 5% of the CPU time for anall-in-memory seqscan.
1 parentc0a2f8c commitdab52ab

File tree

5 files changed

+33
-55
lines changed

5 files changed

+33
-55
lines changed

‎src/backend/executor/execTuples.c

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*
1616
*
1717
* IDENTIFICATION
18-
* $PostgreSQL: pgsql/src/backend/executor/execTuples.c,v 1.89 2005/11/22 18:17:10 momjian Exp $
18+
* $PostgreSQL: pgsql/src/backend/executor/execTuples.c,v 1.90 2005/11/25 04:24:48 tgl Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -402,28 +402,38 @@ ExecStoreTuple(HeapTuple tuple,
402402
Assert(BufferIsValid(buffer) ? (!shouldFree) : true);
403403

404404
/*
405-
*clear outany oldcontents ofthe slot
405+
*Freeany oldphysical tuple belonging tothe slot.
406406
*/
407-
if (!slot->tts_isempty)
408-
ExecClearTuple(slot);
407+
if (slot->tts_shouldFree)
408+
heap_freetuple(slot->tts_tuple);
409409

410410
/*
411-
*store the new tuple into the specified slot.
411+
*Store the new tuple into the specified slot.
412412
*/
413413
slot->tts_isempty= false;
414414
slot->tts_shouldFree=shouldFree;
415415
slot->tts_tuple=tuple;
416416

417+
/* Mark extracted state invalid */
418+
slot->tts_nvalid=0;
419+
417420
/*
418421
* If tuple is on a disk page, keep the page pinned as long as we hold a
419422
* pointer into it. We assume the caller already has such a pin.
423+
*
424+
* This is coded to optimize the case where the slot previously held a
425+
* tuple on the same disk page: in that case releasing and re-acquiring
426+
* the pin is a waste of cycles. This is a common situation during
427+
* seqscans, so it's worth troubling over.
420428
*/
421-
slot->tts_buffer=buffer;
422-
if (BufferIsValid(buffer))
423-
IncrBufferRefCount(buffer);
424-
425-
/* Mark extracted state invalid */
426-
slot->tts_nvalid=0;
429+
if (slot->tts_buffer!=buffer)
430+
{
431+
if (BufferIsValid(slot->tts_buffer))
432+
ReleaseBuffer(slot->tts_buffer);
433+
slot->tts_buffer=buffer;
434+
if (BufferIsValid(buffer))
435+
IncrBufferRefCount(buffer);
436+
}
427437

428438
returnslot;
429439
}

‎src/backend/executor/nodeBitmapHeapscan.c

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
*
2222
*
2323
* IDENTIFICATION
24-
* $PostgreSQL: pgsql/src/backend/executor/nodeBitmapHeapscan.c,v 1.4 2005/10/15 02:49:17 momjian Exp $
24+
* $PostgreSQL: pgsql/src/backend/executor/nodeBitmapHeapscan.c,v 1.5 2005/11/25 04:24:48 tgl Exp $
2525
*
2626
*-------------------------------------------------------------------------
2727
*/
@@ -75,15 +75,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
7575
tbm=node->tbm;
7676
tbmres=node->tbmres;
7777

78-
/*
79-
* Clear any reference to the previously returned tuple. The idea here is
80-
* to not have the tuple slot be the last holder of a pin on that tuple's
81-
* buffer; if it is, we'll need a separate visit to the bufmgr to release
82-
* the buffer.By clearing here, we get to have the release done by
83-
* ReleaseAndReadBuffer, below.
84-
*/
85-
ExecClearTuple(slot);
86-
8778
/*
8879
* Check if we are evaluating PlanQual for tuple of this relation.
8980
* Additional checking is not good, but no other way for now. We could
@@ -94,7 +85,7 @@ BitmapHeapNext(BitmapHeapScanState *node)
9485
estate->es_evTuple[scanrelid-1]!=NULL)
9586
{
9687
if (estate->es_evTupleNull[scanrelid-1])
97-
returnslot;/* return empty slot */
88+
returnExecClearTuple(slot);
9889

9990
ExecStoreTuple(estate->es_evTuple[scanrelid-1],
10091
slot,InvalidBuffer, false);

‎src/backend/executor/nodeIndexscan.c

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/nodeIndexscan.c,v 1.105 2005/11/22 18:17:10 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/nodeIndexscan.c,v 1.106 2005/11/25 04:24:48 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -74,15 +74,6 @@ IndexNext(IndexScanState *node)
7474
slot=node->ss.ss_ScanTupleSlot;
7575
scanrelid= ((IndexScan*)node->ss.ps.plan)->scan.scanrelid;
7676

77-
/*
78-
* Clear any reference to the previously returned tuple. The idea here is
79-
* to not have the tuple slot be the last holder of a pin on that tuple's
80-
* buffer; if it is, we'll need a separate visit to the bufmgr to release
81-
* the buffer.By clearing here, we get to have the release done by
82-
* ReleaseAndReadBuffer inside index_getnext.
83-
*/
84-
ExecClearTuple(slot);
85-
8677
/*
8778
* Check if we are evaluating PlanQual for tuple of this relation.
8879
* Additional checking is not good, but no other way for now. We could
@@ -93,7 +84,7 @@ IndexNext(IndexScanState *node)
9384
estate->es_evTuple[scanrelid-1]!=NULL)
9485
{
9586
if (estate->es_evTupleNull[scanrelid-1])
96-
returnslot;/* return empty slot */
87+
returnExecClearTuple(slot);
9788

9889
ExecStoreTuple(estate->es_evTuple[scanrelid-1],
9990
slot,InvalidBuffer, false);

‎src/backend/executor/nodeSeqscan.c

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/nodeSeqscan.c,v 1.54 2005/10/15 02:49:17 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/nodeSeqscan.c,v 1.55 2005/11/25 04:24:48 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -61,15 +61,6 @@ SeqNext(SeqScanState *node)
6161
direction=estate->es_direction;
6262
slot=node->ss_ScanTupleSlot;
6363

64-
/*
65-
* Clear any reference to the previously returned tuple. The idea here is
66-
* to not have the tuple slot be the last holder of a pin on that tuple's
67-
* buffer; if it is, we'll need a separate visit to the bufmgr to release
68-
* the buffer.By clearing here, we get to have the release done by
69-
* ReleaseAndReadBuffer inside heap_getnext.
70-
*/
71-
ExecClearTuple(slot);
72-
7364
/*
7465
* Check if we are evaluating PlanQual for tuple of this relation.
7566
* Additional checking is not good, but no other way for now. We could
@@ -80,7 +71,7 @@ SeqNext(SeqScanState *node)
8071
estate->es_evTuple[scanrelid-1]!=NULL)
8172
{
8273
if (estate->es_evTupleNull[scanrelid-1])
83-
returnslot;/* return empty slot */
74+
returnExecClearTuple(slot);
8475

8576
ExecStoreTuple(estate->es_evTuple[scanrelid-1],
8677
slot,InvalidBuffer, false);
@@ -93,7 +84,7 @@ SeqNext(SeqScanState *node)
9384

9485
/* Flag for the next call that no more tuples */
9586
estate->es_evTupleNull[scanrelid-1]= true;
96-
return(slot);
87+
returnslot;
9788
}
9889

9990
/*
@@ -115,6 +106,8 @@ SeqNext(SeqScanState *node)
115106
scandesc->rs_cbuf,/* buffer associated with this
116107
* tuple */
117108
false);/* don't pfree this pointer */
109+
else
110+
ExecClearTuple(slot);
118111

119112
returnslot;
120113
}

‎src/backend/executor/nodeTidscan.c

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/nodeTidscan.c,v 1.43 2005/10/15 02:49:17 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/nodeTidscan.c,v 1.44 2005/11/25 04:24:48 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -106,13 +106,6 @@ TidNext(TidScanState *node)
106106
slot=node->ss.ss_ScanTupleSlot;
107107
scanrelid= ((TidScan*)node->ss.ps.plan)->scan.scanrelid;
108108

109-
/*
110-
* Clear any reference to the previously returned tuple. This doesn't
111-
* offer any great performance benefit, but it keeps this code in sync
112-
* with SeqNext and IndexNext.
113-
*/
114-
ExecClearTuple(slot);
115-
116109
/*
117110
* Check if we are evaluating PlanQual for tuple of this relation.
118111
* Additional checking is not good, but no other way for now. We could
@@ -123,7 +116,7 @@ TidNext(TidScanState *node)
123116
estate->es_evTuple[scanrelid-1]!=NULL)
124117
{
125118
if (estate->es_evTupleNull[scanrelid-1])
126-
returnslot;/* return empty slot */
119+
returnExecClearTuple(slot);
127120

128121
/*
129122
* XXX shouldn't we check here to make sure tuple matches TID list? In
@@ -135,7 +128,7 @@ TidNext(TidScanState *node)
135128

136129
/* Flag for the next call that no more tuples */
137130
estate->es_evTupleNull[scanrelid-1]= true;
138-
return(slot);
131+
returnslot;
139132
}
140133

141134
/*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp