Make heap_fetch API more consistent by having the buffer remain pinned
in all cases when keep_buf = true. This allows ANALYZE's inner loop to use heap_release_fetch, which saves multiple buffer lookups for the same page and avoids overestimation of cost by the vacuum cost mechanism.
This commit is contained in:
parent
2c66dcf684
commit
83cd2d8b0f
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.179 2004/10/15 22:39:42 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.180 2004/10/26 16:05:02 tgl Exp $
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* INTERFACE ROUTINES
|
* INTERFACE ROUTINES
|
||||||
@ -878,14 +878,16 @@ heap_getnext(HeapScanDesc scan, ScanDirection direction)
|
|||||||
* is set to the buffer holding the tuple and TRUE is returned. The caller
|
* is set to the buffer holding the tuple and TRUE is returned. The caller
|
||||||
* must unpin the buffer when done with the tuple.
|
* must unpin the buffer when done with the tuple.
|
||||||
*
|
*
|
||||||
* If the tuple is not found, then tuple->t_data is set to NULL, *userbuf
|
* If the tuple is not found (ie, item number references a deleted slot),
|
||||||
* is set to InvalidBuffer, and FALSE is returned.
|
* then tuple->t_data is set to NULL and FALSE is returned.
|
||||||
*
|
*
|
||||||
* If the tuple is found but fails the time qual check, then FALSE will be
|
* If the tuple is found but fails the time qual check, then FALSE is returned
|
||||||
* returned. When the caller specifies keep_buf = true, we retain the pin
|
* but tuple->t_data is left pointing to the tuple.
|
||||||
* on the buffer and return it in *userbuf (so the caller can still access
|
*
|
||||||
* the tuple); when keep_buf = false, the pin is released and *userbuf is set
|
* keep_buf determines what is done with the buffer in the FALSE-result cases.
|
||||||
* to InvalidBuffer.
|
* When the caller specifies keep_buf = true, we retain the pin on the buffer
|
||||||
|
* and return it in *userbuf (so the caller must eventually unpin it); when
|
||||||
|
* keep_buf = false, the pin is released and *userbuf is set to InvalidBuffer.
|
||||||
*
|
*
|
||||||
* It is somewhat inconsistent that we ereport() on invalid block number but
|
* It is somewhat inconsistent that we ereport() on invalid block number but
|
||||||
* return false on invalid item number. This is historical. The only
|
* return false on invalid item number. This is historical. The only
|
||||||
@ -914,6 +916,8 @@ heap_fetch(Relation relation,
|
|||||||
* InvalidBuffer on entry, that buffer will be released before reading
|
* InvalidBuffer on entry, that buffer will be released before reading
|
||||||
* the new page. This saves a separate ReleaseBuffer step and hence
|
* the new page. This saves a separate ReleaseBuffer step and hence
|
||||||
* one entry into the bufmgr when looping through multiple fetches.
|
* one entry into the bufmgr when looping through multiple fetches.
|
||||||
|
* Also, if *userbuf is the same buffer that holds the target tuple,
|
||||||
|
* we avoid bufmgr manipulation altogether.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
heap_release_fetch(Relation relation,
|
heap_release_fetch(Relation relation,
|
||||||
@ -962,8 +966,13 @@ heap_release_fetch(Relation relation,
|
|||||||
if (!ItemIdIsUsed(lp))
|
if (!ItemIdIsUsed(lp))
|
||||||
{
|
{
|
||||||
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||||
ReleaseBuffer(buffer);
|
if (keep_buf)
|
||||||
*userbuf = InvalidBuffer;
|
*userbuf = buffer;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ReleaseBuffer(buffer);
|
||||||
|
*userbuf = InvalidBuffer;
|
||||||
|
}
|
||||||
tuple->t_datamcxt = NULL;
|
tuple->t_datamcxt = NULL;
|
||||||
tuple->t_data = NULL;
|
tuple->t_data = NULL;
|
||||||
return false;
|
return false;
|
||||||
@ -1007,17 +1016,13 @@ heap_release_fetch(Relation relation,
|
|||||||
|
|
||||||
/* Tuple failed time qual, but maybe caller wants to see it anyway. */
|
/* Tuple failed time qual, but maybe caller wants to see it anyway. */
|
||||||
if (keep_buf)
|
if (keep_buf)
|
||||||
{
|
|
||||||
*userbuf = buffer;
|
*userbuf = buffer;
|
||||||
|
else
|
||||||
return false;
|
{
|
||||||
|
ReleaseBuffer(buffer);
|
||||||
|
*userbuf = InvalidBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Okay to release pin on buffer. */
|
|
||||||
ReleaseBuffer(buffer);
|
|
||||||
|
|
||||||
*userbuf = InvalidBuffer;
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.117 2004/10/15 22:39:49 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.118 2004/10/26 16:05:02 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -269,8 +269,8 @@ _bt_check_unique(Relation rel, BTItem btitem, Relation heapRel,
|
|||||||
SetBufferCommitInfoNeedsSave(buf);
|
SetBufferCommitInfoNeedsSave(buf);
|
||||||
}
|
}
|
||||||
LockBuffer(hbuffer, BUFFER_LOCK_UNLOCK);
|
LockBuffer(hbuffer, BUFFER_LOCK_UNLOCK);
|
||||||
ReleaseBuffer(hbuffer);
|
|
||||||
}
|
}
|
||||||
|
ReleaseBuffer(hbuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.77 2004/09/30 23:21:19 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.78 2004/10/26 16:05:03 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -822,11 +822,12 @@ acquire_sample_rows(Relation onerel, HeapTuple *rows, int targrows,
|
|||||||
for (targoffset = FirstOffsetNumber; targoffset <= maxoffset; targoffset++)
|
for (targoffset = FirstOffsetNumber; targoffset <= maxoffset; targoffset++)
|
||||||
{
|
{
|
||||||
HeapTupleData targtuple;
|
HeapTupleData targtuple;
|
||||||
Buffer tupbuffer;
|
|
||||||
|
|
||||||
ItemPointerSet(&targtuple.t_self, targblock, targoffset);
|
ItemPointerSet(&targtuple.t_self, targblock, targoffset);
|
||||||
if (heap_fetch(onerel, SnapshotNow, &targtuple, &tupbuffer,
|
/* We use heap_release_fetch to avoid useless bufmgr traffic */
|
||||||
false, NULL))
|
if (heap_release_fetch(onerel, SnapshotNow,
|
||||||
|
&targtuple, &targbuffer,
|
||||||
|
true, NULL))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* The first targrows live rows are simply copied into the
|
* The first targrows live rows are simply copied into the
|
||||||
@ -869,9 +870,6 @@ acquire_sample_rows(Relation onerel, HeapTuple *rows, int targrows,
|
|||||||
rowstoskip -= 1;
|
rowstoskip -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* must release the extra pin acquired by heap_fetch */
|
|
||||||
ReleaseBuffer(tupbuffer);
|
|
||||||
|
|
||||||
liverows += 1;
|
liverows += 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -886,7 +884,7 @@ acquire_sample_rows(Relation onerel, HeapTuple *rows, int targrows,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now release the initial pin on the page */
|
/* Now release the pin on the page */
|
||||||
ReleaseBuffer(targbuffer);
|
ReleaseBuffer(targbuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user