mirror of
https://github.com/postgres/postgres.git
synced 2025-05-25 00:04:05 -04:00
Push the responsibility for handling ignore_killed_tuples down into
_bt_checkkeys(), instead of checking it in the top-level nbtree.c routines as formerly. This saves a little bit of loop overhead, but more importantly it lets us skip performing the index key comparisons for dead tuples.
This commit is contained in:
parent
f1b059af12
commit
cefcbbf1fd
@ -12,7 +12,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.134 2005/11/22 18:17:06 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.135 2005/12/07 19:37:53 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -288,21 +288,6 @@ btgettuple(PG_FUNCTION_ARGS)
|
|||||||
else
|
else
|
||||||
res = _bt_first(scan, dir);
|
res = _bt_first(scan, dir);
|
||||||
|
|
||||||
/*
|
|
||||||
* Skip killed tuples if asked to.
|
|
||||||
*/
|
|
||||||
if (scan->ignore_killed_tuples)
|
|
||||||
{
|
|
||||||
while (res)
|
|
||||||
{
|
|
||||||
offnum = ItemPointerGetOffsetNumber(&(scan->currentItemData));
|
|
||||||
page = BufferGetPage(so->btso_curbuf);
|
|
||||||
if (!ItemIdDeleted(PageGetItemId(page, offnum)))
|
|
||||||
break;
|
|
||||||
res = _bt_next(scan, dir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Save heap TID to use it in _bt_restscan. Then release the read lock on
|
* Save heap TID to use it in _bt_restscan. Then release the read lock on
|
||||||
* the buffer so that we aren't blocking other backends.
|
* the buffer so that we aren't blocking other backends.
|
||||||
@ -353,25 +338,6 @@ btgetmulti(PG_FUNCTION_ARGS)
|
|||||||
res = _bt_next(scan, ForwardScanDirection);
|
res = _bt_next(scan, ForwardScanDirection);
|
||||||
else
|
else
|
||||||
res = _bt_first(scan, ForwardScanDirection);
|
res = _bt_first(scan, ForwardScanDirection);
|
||||||
|
|
||||||
/*
|
|
||||||
* Skip killed tuples if asked to.
|
|
||||||
*/
|
|
||||||
if (scan->ignore_killed_tuples)
|
|
||||||
{
|
|
||||||
while (res)
|
|
||||||
{
|
|
||||||
Page page;
|
|
||||||
OffsetNumber offnum;
|
|
||||||
|
|
||||||
offnum = ItemPointerGetOffsetNumber(&(scan->currentItemData));
|
|
||||||
page = BufferGetPage(so->btso_curbuf);
|
|
||||||
if (!ItemIdDeleted(PageGetItemId(page, offnum)))
|
|
||||||
break;
|
|
||||||
res = _bt_next(scan, ForwardScanDirection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!res)
|
if (!res)
|
||||||
break;
|
break;
|
||||||
/* Save tuple ID, and continue scanning */
|
/* Save tuple ID, and continue scanning */
|
||||||
@ -385,9 +351,8 @@ btgetmulti(PG_FUNCTION_ARGS)
|
|||||||
*/
|
*/
|
||||||
if (res)
|
if (res)
|
||||||
{
|
{
|
||||||
((BTScanOpaque) scan->opaque)->curHeapIptr = scan->xs_ctup.t_self;
|
so->curHeapIptr = scan->xs_ctup.t_self;
|
||||||
LockBuffer(((BTScanOpaque) scan->opaque)->btso_curbuf,
|
LockBuffer(so->btso_curbuf, BUFFER_LOCK_UNLOCK);
|
||||||
BUFFER_LOCK_UNLOCK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*returned_tids = ntids;
|
*returned_tids = ntids;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.98 2005/12/07 18:03:48 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.99 2005/12/07 19:37:53 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -423,8 +423,6 @@ _bt_next(IndexScanDesc scan, ScanDirection dir)
|
|||||||
Page page;
|
Page page;
|
||||||
OffsetNumber offnum;
|
OffsetNumber offnum;
|
||||||
ItemPointer current;
|
ItemPointer current;
|
||||||
BTItem btitem;
|
|
||||||
IndexTuple itup;
|
|
||||||
BTScanOpaque so;
|
BTScanOpaque so;
|
||||||
bool continuescan;
|
bool continuescan;
|
||||||
|
|
||||||
@ -445,13 +443,10 @@ _bt_next(IndexScanDesc scan, ScanDirection dir)
|
|||||||
/* current is the next candidate tuple to return */
|
/* current is the next candidate tuple to return */
|
||||||
offnum = ItemPointerGetOffsetNumber(current);
|
offnum = ItemPointerGetOffsetNumber(current);
|
||||||
page = BufferGetPage(buf);
|
page = BufferGetPage(buf);
|
||||||
btitem = (BTItem) PageGetItem(page, PageGetItemId(page, offnum));
|
|
||||||
itup = &btitem->bti_itup;
|
|
||||||
|
|
||||||
if (_bt_checkkeys(scan, itup, dir, &continuescan))
|
if (_bt_checkkeys(scan, page, offnum, dir, &continuescan))
|
||||||
{
|
{
|
||||||
/* tuple passes all scan key conditions, so return it */
|
/* tuple passes all scan key conditions, so return it */
|
||||||
scan->xs_ctup.t_self = itup->t_tid;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -485,8 +480,6 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
Page page;
|
Page page;
|
||||||
BTStack stack;
|
BTStack stack;
|
||||||
OffsetNumber offnum;
|
OffsetNumber offnum;
|
||||||
BTItem btitem;
|
|
||||||
IndexTuple itup;
|
|
||||||
ItemPointer current;
|
ItemPointer current;
|
||||||
BlockNumber blkno;
|
BlockNumber blkno;
|
||||||
StrategyNumber strat;
|
StrategyNumber strat;
|
||||||
@ -848,14 +841,11 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
/* okay, current item pointer for the scan is right */
|
/* okay, current item pointer for the scan is right */
|
||||||
offnum = ItemPointerGetOffsetNumber(current);
|
offnum = ItemPointerGetOffsetNumber(current);
|
||||||
page = BufferGetPage(buf);
|
page = BufferGetPage(buf);
|
||||||
btitem = (BTItem) PageGetItem(page, PageGetItemId(page, offnum));
|
|
||||||
itup = &btitem->bti_itup;
|
|
||||||
|
|
||||||
/* is the first item actually acceptable? */
|
/* is the first item actually acceptable? */
|
||||||
if (_bt_checkkeys(scan, itup, dir, &continuescan))
|
if (_bt_checkkeys(scan, page, offnum, dir, &continuescan))
|
||||||
{
|
{
|
||||||
/* yes, return it */
|
/* yes, return it */
|
||||||
scan->xs_ctup.t_self = itup->t_tid;
|
|
||||||
res = true;
|
res = true;
|
||||||
}
|
}
|
||||||
else if (continuescan)
|
else if (continuescan)
|
||||||
@ -1215,8 +1205,6 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
|
|||||||
OffsetNumber maxoff;
|
OffsetNumber maxoff;
|
||||||
OffsetNumber start;
|
OffsetNumber start;
|
||||||
BlockNumber blkno;
|
BlockNumber blkno;
|
||||||
BTItem btitem;
|
|
||||||
IndexTuple itup;
|
|
||||||
BTScanOpaque so;
|
BTScanOpaque so;
|
||||||
bool res;
|
bool res;
|
||||||
bool continuescan;
|
bool continuescan;
|
||||||
@ -1284,16 +1272,12 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
|
|||||||
page = BufferGetPage(buf);
|
page = BufferGetPage(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
btitem = (BTItem) PageGetItem(page, PageGetItemId(page, start));
|
|
||||||
itup = &(btitem->bti_itup);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Okay, we are on the first or last tuple. Does it pass all the quals?
|
* Okay, we are on the first or last tuple. Does it pass all the quals?
|
||||||
*/
|
*/
|
||||||
if (_bt_checkkeys(scan, itup, dir, &continuescan))
|
if (_bt_checkkeys(scan, page, start, dir, &continuescan))
|
||||||
{
|
{
|
||||||
/* yes, return it */
|
/* yes, return it */
|
||||||
scan->xs_ctup.t_self = itup->t_tid;
|
|
||||||
res = true;
|
res = true;
|
||||||
}
|
}
|
||||||
else if (continuescan)
|
else if (continuescan)
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtutils.c,v 1.66 2005/11/22 18:17:06 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtutils.c,v 1.67 2005/12/07 19:37:53 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -477,30 +477,77 @@ _bt_preprocess_keys(IndexScanDesc scan)
|
|||||||
/*
|
/*
|
||||||
* Test whether an indextuple satisfies all the scankey conditions.
|
* Test whether an indextuple satisfies all the scankey conditions.
|
||||||
*
|
*
|
||||||
|
* If so, copy its TID into scan->xs_ctup.t_self, and return TRUE.
|
||||||
|
* If not, return FALSE (xs_ctup is not changed).
|
||||||
|
*
|
||||||
* If the tuple fails to pass the qual, we also determine whether there's
|
* If the tuple fails to pass the qual, we also determine whether there's
|
||||||
* any need to continue the scan beyond this tuple, and set *continuescan
|
* any need to continue the scan beyond this tuple, and set *continuescan
|
||||||
* accordingly. See comments for _bt_preprocess_keys(), above, about how
|
* accordingly. See comments for _bt_preprocess_keys(), above, about how
|
||||||
* this is done.
|
* this is done.
|
||||||
|
*
|
||||||
|
* scan: index scan descriptor
|
||||||
|
* page: buffer page containing index tuple
|
||||||
|
* offnum: offset number of index tuple (must be a valid item!)
|
||||||
|
* dir: direction we are scanning in
|
||||||
|
* continuescan: output parameter (will be set correctly in all cases)
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
_bt_checkkeys(IndexScanDesc scan, IndexTuple tuple,
|
_bt_checkkeys(IndexScanDesc scan,
|
||||||
|
Page page, OffsetNumber offnum,
|
||||||
ScanDirection dir, bool *continuescan)
|
ScanDirection dir, bool *continuescan)
|
||||||
{
|
{
|
||||||
BTScanOpaque so = (BTScanOpaque) scan->opaque;
|
ItemId iid = PageGetItemId(page, offnum);
|
||||||
int keysz = so->numberOfKeys;
|
bool tuple_valid;
|
||||||
int ikey;
|
BTItem btitem;
|
||||||
|
IndexTuple tuple;
|
||||||
TupleDesc tupdesc;
|
TupleDesc tupdesc;
|
||||||
|
BTScanOpaque so;
|
||||||
|
int keysz;
|
||||||
|
int ikey;
|
||||||
ScanKey key;
|
ScanKey key;
|
||||||
|
|
||||||
*continuescan = true;
|
*continuescan = true; /* default assumption */
|
||||||
|
|
||||||
/* If no keys, always scan the whole index */
|
/*
|
||||||
if (keysz == 0)
|
* If the scan specifies not to return killed tuples, then we treat
|
||||||
return true;
|
* a killed tuple as not passing the qual. Most of the time, it's a
|
||||||
|
* win to not bother examining the tuple's index keys, but just return
|
||||||
|
* immediately with continuescan = true to proceed to the next tuple.
|
||||||
|
* However, if this is the last tuple on the page, we should check
|
||||||
|
* the index keys to prevent uselessly advancing to the next page.
|
||||||
|
*/
|
||||||
|
if (scan->ignore_killed_tuples && ItemIdDeleted(iid))
|
||||||
|
{
|
||||||
|
/* return immediately if there are more tuples on the page */
|
||||||
|
if (ScanDirectionIsForward(dir))
|
||||||
|
{
|
||||||
|
if (offnum < PageGetMaxOffsetNumber(page))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BTPageOpaque opaque = (BTPageOpaque) PageGetSpecialPointer(page);
|
||||||
|
|
||||||
|
if (offnum > P_FIRSTDATAKEY(opaque))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* OK, we want to check the keys, but we'll return FALSE even
|
||||||
|
* if the tuple passes the key tests.
|
||||||
|
*/
|
||||||
|
tuple_valid = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
tuple_valid = true;
|
||||||
|
|
||||||
|
btitem = (BTItem) PageGetItem(page, iid);
|
||||||
|
tuple = &btitem->bti_itup;
|
||||||
|
|
||||||
IncrIndexProcessed();
|
IncrIndexProcessed();
|
||||||
|
|
||||||
tupdesc = RelationGetDescr(scan->indexRelation);
|
tupdesc = RelationGetDescr(scan->indexRelation);
|
||||||
|
so = (BTScanOpaque) scan->opaque;
|
||||||
|
keysz = so->numberOfKeys;
|
||||||
|
|
||||||
for (key = so->keyData, ikey = 0; ikey < keysz; key++, ikey++)
|
for (key = so->keyData, ikey = 0; ikey < keysz; key++, ikey++)
|
||||||
{
|
{
|
||||||
@ -592,6 +639,9 @@ _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we get here, the tuple passes all quals. */
|
/* If we get here, the tuple passes all index quals. */
|
||||||
return true;
|
if (tuple_valid)
|
||||||
|
scan->xs_ctup.t_self = tuple->t_tid;
|
||||||
|
|
||||||
|
return tuple_valid;
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.88 2005/11/06 19:29:01 tgl Exp $
|
* $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.89 2005/12/07 19:37:53 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -467,8 +467,9 @@ extern ScanKey _bt_mkscankey_nodata(Relation rel);
|
|||||||
extern void _bt_freeskey(ScanKey skey);
|
extern void _bt_freeskey(ScanKey skey);
|
||||||
extern void _bt_freestack(BTStack stack);
|
extern void _bt_freestack(BTStack stack);
|
||||||
extern void _bt_preprocess_keys(IndexScanDesc scan);
|
extern void _bt_preprocess_keys(IndexScanDesc scan);
|
||||||
extern bool _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple,
|
extern bool _bt_checkkeys(IndexScanDesc scan,
|
||||||
ScanDirection dir, bool *continuescan);
|
Page page, OffsetNumber offnum,
|
||||||
|
ScanDirection dir, bool *continuescan);
|
||||||
extern BTItem _bt_formitem(IndexTuple itup);
|
extern BTItem _bt_formitem(IndexTuple itup);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user