postgres.git / summary / log / commit / refs

commit    3f44959f47460fb350d25d760cf2384f9aa14e9a
Author:   Peter Geoghegan <pg@bowt.ie>
Date:     Sun Aug 11 19:42:52 2024 +0000
First released in: 18.0

    Avoid unneeded nbtree backwards scan buffer locks.
    
    Teach nbtree backwards scans to avoid relocking a just-read leaf page to
    read its current left sibling link when it isn't truly necessary.  This
    happened inside _bt_readnextpage whenever _bt_readpage had already
    determined that there'll be no further matches to the left (or at least
    none for the current primitive index scan, for a scan with array keys).
    
    A new precheck inside _bt_readnextpage is all that we need to avoid
    these useless lock acquisitions.  Arguably, using a precheck like this
    was a missed opportunity for commit 2ed5b87f96, which taught nbtree to
    drop leaf page pins early to avoid blocking cleanup by VACUUM.  Forwards
    scans already managed to avoid relocking the page like this.
    
    The optimization added by this commit is particularly helpful with
    backwards scans that use array keys where the scan must perform multiple
    primitive index scans.  Such backwards scans will now avoid a useless
    leaf page re-lock at the end of each primitive index scan.
    
    Note that this commit does not attempt to avoid needlessly re-locking a
    leaf page that was just read when the scan must follow the leaf page's
    left link.  That more ambitious optimization could work by stashing the
    left link when the page is first read by a backwards scan, allowing the
    subsequent _bt_readnextpage call to optimistically skip re-reading the
    original page just to get a new copy of its left link.  For now we only
    address cases where we don't care about our original page's left link.
    
    Author: Peter Geoghegan <pg@bowt.ie>
    Reviewed-By: Matthias van de Meent <boekewurm+postgres@gmail.com>
    Discussion: https://postgr.es/m/CAH2-Wz=xgs7PojG=EUvhgadwENzu_mY_riNh-w9wFPsaS717ew@mail.gmail.com


src/backend/access/nbtree/nbtsearch.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c index 57bcfc7e4c6..1fad41391b5 100644 --- a/src/backend/access/nbtree/nbtsearch.c +++ b/src/backend/access/nbtree/nbtsearch.c @@ -1916,16 +1916,20 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum, } } } + /* When !continuescan, there can't be any more matches, so stop */ if (!pstate.continuescan) - { - /* there can't be any more matches, so stop */ - so->currPos.moreLeft = false; break; - } offnum = OffsetNumberPrev(offnum); } + /* + * We don't need to visit page to the left when no more matches will + * be found there + */ + if (!pstate.continuescan || P_LEFTMOST(opaque)) + so->currPos.moreLeft = false; + Assert(itemIndex >= 0); so->currPos.firstItem = itemIndex; so->currPos.lastItem = MaxTIDsPerBTreePage - 1; @@ -2240,6 +2244,15 @@ _bt_readnextpage(IndexScanDesc scan, BlockNumber blkno, ScanDirection dir) so->currPos.currPage = blkno; } + /* Done if we know that the left sibling link isn't of interest */ + if (!so->currPos.moreLeft) + { + BTScanPosUnpinIfPinned(so->currPos); + _bt_parallel_done(scan); + BTScanPosInvalidate(so->currPos); + return false; + } + /* * Walk left to the next page with data. This is much more complex * than the walk-right case because of the possibility that the page @@ -2260,7 +2273,7 @@ _bt_readnextpage(IndexScanDesc scan, BlockNumber blkno, ScanDirection dir) for (;;) { - /* Done if we know there are no matching keys to the left */ + /* Done if we know that the left sibling link isn't of interest */ if (!so->currPos.moreLeft) { _bt_relbuf(rel, so->currPos.buf); [parent: f011e82c2c88]