Commit cefcbbf1 authored by Tom Lane's avatar Tom Lane

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.
parent f1b059af
...@@ -12,7 +12,7 @@ ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 @@ ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 @@ ...@@ -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) ...@@ -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 the scan specifies not to return killed tuples, then we treat
* 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;
/* If no keys, always scan the whole index */ btitem = (BTItem) PageGetItem(page, iid);
if (keysz == 0) tuple = &btitem->bti_itup;
return true;
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, ...@@ -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 @@ ...@@ -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,7 +467,8 @@ extern ScanKey _bt_mkscankey_nodata(Relation rel); ...@@ -467,7 +467,8 @@ 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,
Page page, OffsetNumber offnum,
ScanDirection dir, bool *continuescan); ScanDirection dir, bool *continuescan);
extern BTItem _bt_formitem(IndexTuple itup); extern BTItem _bt_formitem(IndexTuple itup);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment