mirror of
https://github.com/postgres/postgres.git
synced 2025-11-10 17:42:29 +03:00
Tweak indexscan and seqscan code to arrange that steps from one page to
the next are handled by ReleaseAndReadBuffer rather than separate ReleaseBuffer and ReadBuffer calls. This cuts the number of acquisitions of the BufMgrLock by a factor of 2 (possibly more, if an indexscan happens to pull successive rows from the same heap page). Unfortunately this doesn't seem enough to get us out of the recently discussed context-switch storm problem, but it's surely worth doing anyway.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.111 2004/01/07 18:56:24 neilc Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.112 2004/04/21 18:24:25 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -297,9 +297,7 @@ _bt_check_unique(Relation rel, BTItem btitem, Relation heapRel,
|
||||
for (;;)
|
||||
{
|
||||
nblkno = opaque->btpo_next;
|
||||
if (nbuf != InvalidBuffer)
|
||||
_bt_relbuf(rel, nbuf);
|
||||
nbuf = _bt_getbuf(rel, nblkno, BT_READ);
|
||||
nbuf = _bt_relandgetbuf(rel, nbuf, nblkno, BT_READ);
|
||||
page = BufferGetPage(nbuf);
|
||||
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
|
||||
if (!P_IGNORE(opaque))
|
||||
@@ -454,9 +452,7 @@ _bt_insertonpg(Relation rel,
|
||||
{
|
||||
BlockNumber rblkno = lpageop->btpo_next;
|
||||
|
||||
if (rbuf != InvalidBuffer)
|
||||
_bt_relbuf(rel, rbuf);
|
||||
rbuf = _bt_getbuf(rel, rblkno, BT_WRITE);
|
||||
rbuf = _bt_relandgetbuf(rel, rbuf, rblkno, BT_WRITE);
|
||||
page = BufferGetPage(rbuf);
|
||||
lpageop = (BTPageOpaque) PageGetSpecialPointer(page);
|
||||
if (!P_IGNORE(lpageop))
|
||||
@@ -1357,7 +1353,7 @@ _bt_getstackbuf(Relation rel, BTStack stack, int access)
|
||||
if (P_RIGHTMOST(opaque))
|
||||
{
|
||||
_bt_relbuf(rel, buf);
|
||||
return (InvalidBuffer);
|
||||
return InvalidBuffer;
|
||||
}
|
||||
blkno = opaque->btpo_next;
|
||||
start = InvalidOffsetNumber;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtpage.c,v 1.74 2003/12/21 01:23:06 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtpage.c,v 1.75 2004/04/21 18:24:25 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Postgres btree pages look like ordinary relation pages. The opaque
|
||||
@@ -262,11 +262,15 @@ _bt_getroot(Relation rel, int access)
|
||||
Assert(rootblkno != P_NONE);
|
||||
rootlevel = metad->btm_fastlevel;
|
||||
|
||||
_bt_relbuf(rel, metabuf); /* done with the meta page */
|
||||
/*
|
||||
* We are done with the metapage; arrange to release it via
|
||||
* first _bt_relandgetbuf call
|
||||
*/
|
||||
rootbuf = metabuf;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
rootbuf = _bt_getbuf(rel, rootblkno, BT_READ);
|
||||
rootbuf = _bt_relandgetbuf(rel, rootbuf, rootblkno, BT_READ);
|
||||
rootpage = BufferGetPage(rootbuf);
|
||||
rootopaque = (BTPageOpaque) PageGetSpecialPointer(rootpage);
|
||||
|
||||
@@ -278,8 +282,6 @@ _bt_getroot(Relation rel, int access)
|
||||
elog(ERROR, "no live root page found in \"%s\"",
|
||||
RelationGetRelationName(rel));
|
||||
rootblkno = rootopaque->btpo_next;
|
||||
|
||||
_bt_relbuf(rel, rootbuf);
|
||||
}
|
||||
|
||||
/* Note: can't check btpo.level on deleted pages */
|
||||
@@ -352,11 +354,15 @@ _bt_gettrueroot(Relation rel)
|
||||
rootblkno = metad->btm_root;
|
||||
rootlevel = metad->btm_level;
|
||||
|
||||
_bt_relbuf(rel, metabuf); /* done with the meta page */
|
||||
/*
|
||||
* We are done with the metapage; arrange to release it via
|
||||
* first _bt_relandgetbuf call
|
||||
*/
|
||||
rootbuf = metabuf;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
rootbuf = _bt_getbuf(rel, rootblkno, BT_READ);
|
||||
rootbuf = _bt_relandgetbuf(rel, rootbuf, rootblkno, BT_READ);
|
||||
rootpage = BufferGetPage(rootbuf);
|
||||
rootopaque = (BTPageOpaque) PageGetSpecialPointer(rootpage);
|
||||
|
||||
@@ -368,8 +374,6 @@ _bt_gettrueroot(Relation rel)
|
||||
elog(ERROR, "no live root page found in \"%s\"",
|
||||
RelationGetRelationName(rel));
|
||||
rootblkno = rootopaque->btpo_next;
|
||||
|
||||
_bt_relbuf(rel, rootbuf);
|
||||
}
|
||||
|
||||
/* Note: can't check btpo.level on deleted pages */
|
||||
@@ -492,6 +496,28 @@ _bt_getbuf(Relation rel, BlockNumber blkno, int access)
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* _bt_relandgetbuf() -- release a locked buffer and get another one.
|
||||
*
|
||||
* This is equivalent to _bt_relbuf followed by _bt_getbuf, with the
|
||||
* exception that blkno may not be P_NEW. Also, if obuf is InvalidBuffer
|
||||
* then it reduces to just _bt_getbuf; allowing this case simplifies some
|
||||
* callers. The motivation for using this is to avoid two entries to the
|
||||
* bufmgr when one will do.
|
||||
*/
|
||||
Buffer
|
||||
_bt_relandgetbuf(Relation rel, Buffer obuf, BlockNumber blkno, int access)
|
||||
{
|
||||
Buffer buf;
|
||||
|
||||
Assert(blkno != P_NEW);
|
||||
if (BufferIsValid(obuf))
|
||||
LockBuffer(obuf, BUFFER_LOCK_UNLOCK);
|
||||
buf = ReleaseAndReadBuffer(obuf, rel, blkno);
|
||||
LockBuffer(buf, access);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* _bt_relbuf() -- release a locked buffer.
|
||||
*
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.113 2004/02/10 03:42:43 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.114 2004/04/21 18:24:26 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -919,9 +919,7 @@ _bt_restscan(IndexScanDesc scan)
|
||||
for (;;)
|
||||
{
|
||||
blkno = opaque->btpo_next;
|
||||
if (nextbuf != InvalidBuffer)
|
||||
_bt_relbuf(rel, nextbuf);
|
||||
nextbuf = _bt_getbuf(rel, blkno, BT_READ);
|
||||
nextbuf = _bt_relandgetbuf(rel, nextbuf, blkno, BT_READ);
|
||||
page = BufferGetPage(nextbuf);
|
||||
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
|
||||
if (!P_IGNORE(opaque))
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.86 2003/12/21 17:52:34 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.87 2004/04/21 18:24:26 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -108,8 +108,7 @@ _bt_search(Relation rel, int keysz, ScanKey scankey, bool nextkey,
|
||||
new_stack->bts_parent = stack_in;
|
||||
|
||||
/* drop the read lock on the parent page, acquire one on the child */
|
||||
_bt_relbuf(rel, *bufP);
|
||||
*bufP = _bt_getbuf(rel, blkno, BT_READ);
|
||||
*bufP = _bt_relandgetbuf(rel, *bufP, blkno, BT_READ);
|
||||
|
||||
/* okay, all set to move down a level */
|
||||
stack_in = new_stack;
|
||||
@@ -178,8 +177,7 @@ _bt_moveright(Relation rel,
|
||||
/* step right one page */
|
||||
BlockNumber rblkno = opaque->btpo_next;
|
||||
|
||||
_bt_relbuf(rel, buf);
|
||||
buf = _bt_getbuf(rel, rblkno, access);
|
||||
buf = _bt_relandgetbuf(rel, buf, rblkno, access);
|
||||
page = BufferGetPage(buf);
|
||||
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
|
||||
}
|
||||
@@ -933,8 +931,7 @@ _bt_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir)
|
||||
}
|
||||
/* step right one page */
|
||||
blkno = opaque->btpo_next;
|
||||
_bt_relbuf(rel, *bufP);
|
||||
*bufP = _bt_getbuf(rel, blkno, BT_READ);
|
||||
*bufP = _bt_relandgetbuf(rel, *bufP, blkno, BT_READ);
|
||||
page = BufferGetPage(*bufP);
|
||||
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
|
||||
if (!P_IGNORE(opaque))
|
||||
@@ -1041,8 +1038,7 @@ _bt_walk_left(Relation rel, Buffer buf)
|
||||
obknum = BufferGetBlockNumber(buf);
|
||||
/* step left */
|
||||
blkno = lblkno = opaque->btpo_prev;
|
||||
_bt_relbuf(rel, buf);
|
||||
buf = _bt_getbuf(rel, blkno, BT_READ);
|
||||
buf = _bt_relandgetbuf(rel, buf, blkno, BT_READ);
|
||||
page = BufferGetPage(buf);
|
||||
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
|
||||
|
||||
@@ -1069,15 +1065,13 @@ _bt_walk_left(Relation rel, Buffer buf)
|
||||
if (P_RIGHTMOST(opaque) || ++tries > 4)
|
||||
break;
|
||||
blkno = opaque->btpo_next;
|
||||
_bt_relbuf(rel, buf);
|
||||
buf = _bt_getbuf(rel, blkno, BT_READ);
|
||||
buf = _bt_relandgetbuf(rel, buf, blkno, BT_READ);
|
||||
page = BufferGetPage(buf);
|
||||
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
|
||||
}
|
||||
|
||||
/* Return to the original page to see what's up */
|
||||
_bt_relbuf(rel, buf);
|
||||
buf = _bt_getbuf(rel, obknum, BT_READ);
|
||||
buf = _bt_relandgetbuf(rel, buf, obknum, BT_READ);
|
||||
page = BufferGetPage(buf);
|
||||
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
|
||||
if (P_ISDELETED(opaque))
|
||||
@@ -1094,8 +1088,7 @@ _bt_walk_left(Relation rel, Buffer buf)
|
||||
elog(ERROR, "fell off the end of \"%s\"",
|
||||
RelationGetRelationName(rel));
|
||||
blkno = opaque->btpo_next;
|
||||
_bt_relbuf(rel, buf);
|
||||
buf = _bt_getbuf(rel, blkno, BT_READ);
|
||||
buf = _bt_relandgetbuf(rel, buf, blkno, BT_READ);
|
||||
page = BufferGetPage(buf);
|
||||
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
|
||||
if (!P_ISDELETED(opaque))
|
||||
@@ -1177,8 +1170,7 @@ _bt_get_endpoint(Relation rel, uint32 level, bool rightmost)
|
||||
if (blkno == P_NONE)
|
||||
elog(ERROR, "fell off the end of \"%s\"",
|
||||
RelationGetRelationName(rel));
|
||||
_bt_relbuf(rel, buf);
|
||||
buf = _bt_getbuf(rel, blkno, BT_READ);
|
||||
buf = _bt_relandgetbuf(rel, buf, blkno, BT_READ);
|
||||
page = BufferGetPage(buf);
|
||||
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
|
||||
}
|
||||
@@ -1199,8 +1191,7 @@ _bt_get_endpoint(Relation rel, uint32 level, bool rightmost)
|
||||
itup = &(btitem->bti_itup);
|
||||
blkno = ItemPointerGetBlockNumber(&(itup->t_tid));
|
||||
|
||||
_bt_relbuf(rel, buf);
|
||||
buf = _bt_getbuf(rel, blkno, BT_READ);
|
||||
buf = _bt_relandgetbuf(rel, buf, blkno, BT_READ);
|
||||
page = BufferGetPage(buf);
|
||||
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user