]> granicus.if.org Git - postgresql/commitdiff
Push the responsibility for handling ignore_killed_tuples down into
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 7 Dec 2005 19:37:53 +0000 (19:37 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 7 Dec 2005 19:37:53 +0000 (19:37 +0000)
_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.

src/backend/access/nbtree/nbtree.c
src/backend/access/nbtree/nbtsearch.c
src/backend/access/nbtree/nbtutils.c
src/include/access/nbtree.h

index 70aca882e6c28671859a9eebec82a10c9a592932..589a49a2cead6a709cd9344b484813d2be5c0a6d 100644 (file)
@@ -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.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
                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
         * the buffer so that we aren't blocking other backends.
@@ -353,25 +338,6 @@ btgetmulti(PG_FUNCTION_ARGS)
                        res = _bt_next(scan, ForwardScanDirection);
                else
                        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)
                        break;
                /* Save tuple ID, and continue scanning */
@@ -385,9 +351,8 @@ btgetmulti(PG_FUNCTION_ARGS)
         */
        if (res)
        {
-               ((BTScanOpaque) scan->opaque)->curHeapIptr = scan->xs_ctup.t_self;
-               LockBuffer(((BTScanOpaque) scan->opaque)->btso_curbuf,
-                                  BUFFER_LOCK_UNLOCK);
+               so->curHeapIptr = scan->xs_ctup.t_self;
+               LockBuffer(so->btso_curbuf, BUFFER_LOCK_UNLOCK);
        }
 
        *returned_tids = ntids;
index dd4f500842b37ea57b30f634cd2a6ac9c00f182b..4cd79997292c82ec9d7a741a6cf2857d764f5025 100644 (file)
@@ -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.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;
        OffsetNumber offnum;
        ItemPointer current;
-       BTItem          btitem;
-       IndexTuple      itup;
        BTScanOpaque so;
        bool            continuescan;
 
@@ -445,13 +443,10 @@ _bt_next(IndexScanDesc scan, ScanDirection dir)
                /* current is the next candidate tuple to return */
                offnum = ItemPointerGetOffsetNumber(current);
                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 */
-                       scan->xs_ctup.t_self = itup->t_tid;
                        return true;
                }
 
@@ -485,8 +480,6 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
        Page            page;
        BTStack         stack;
        OffsetNumber offnum;
-       BTItem          btitem;
-       IndexTuple      itup;
        ItemPointer current;
        BlockNumber blkno;
        StrategyNumber strat;
@@ -848,14 +841,11 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
        /* okay, current item pointer for the scan is right */
        offnum = ItemPointerGetOffsetNumber(current);
        page = BufferGetPage(buf);
-       btitem = (BTItem) PageGetItem(page, PageGetItemId(page, offnum));
-       itup = &btitem->bti_itup;
 
        /* is the first item actually acceptable? */
-       if (_bt_checkkeys(scan, itup, dir, &continuescan))
+       if (_bt_checkkeys(scan, page, offnum, dir, &continuescan))
        {
                /* yes, return it */
-               scan->xs_ctup.t_self = itup->t_tid;
                res = true;
        }
        else if (continuescan)
@@ -1215,8 +1205,6 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
        OffsetNumber maxoff;
        OffsetNumber start;
        BlockNumber blkno;
-       BTItem          btitem;
-       IndexTuple      itup;
        BTScanOpaque so;
        bool            res;
        bool            continuescan;
@@ -1284,16 +1272,12 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
                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?
         */
-       if (_bt_checkkeys(scan, itup, dir, &continuescan))
+       if (_bt_checkkeys(scan, page, start, dir, &continuescan))
        {
                /* yes, return it */
-               scan->xs_ctup.t_self = itup->t_tid;
                res = true;
        }
        else if (continuescan)
index f4c2243943b2c5ffb1f8b216fc592c17cdb11b34..7a18fcf0abbf65161aa5b54c1da81be5d2878f62 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * 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.
  *
+ * 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
  * any need to continue the scan beyond this tuple, and set *continuescan
  * accordingly.  See comments for _bt_preprocess_keys(), above, about how
  * 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
-_bt_checkkeys(IndexScanDesc scan, IndexTuple tuple,
+_bt_checkkeys(IndexScanDesc scan,
+                         Page page, OffsetNumber offnum,
                          ScanDirection dir, bool *continuescan)
 {
-       BTScanOpaque so = (BTScanOpaque) scan->opaque;
-       int                     keysz = so->numberOfKeys;
-       int                     ikey;
+       ItemId          iid = PageGetItemId(page, offnum);
+       bool            tuple_valid;
+       BTItem          btitem;
+       IndexTuple      tuple;
        TupleDesc       tupdesc;
+       BTScanOpaque so;
+       int                     keysz;
+       int                     ikey;
        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 */
-       if (keysz == 0)
-               return true;
+       btitem = (BTItem) PageGetItem(page, iid);
+       tuple = &btitem->bti_itup;
 
        IncrIndexProcessed();
 
        tupdesc = RelationGetDescr(scan->indexRelation);
+       so = (BTScanOpaque) scan->opaque;
+       keysz = so->numberOfKeys;
 
        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. */
-       return true;
+       /* If we get here, the tuple passes all index quals. */
+       if (tuple_valid)
+               scan->xs_ctup.t_self = tuple->t_tid;
+
+       return tuple_valid;
 }
index 9cd00d554da41c1fef8845b65cda56eb7e4203dc..5a3ec5f1efeddcec56fc91ce4e577e14ffaa48fb 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * 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_freestack(BTStack stack);
 extern void _bt_preprocess_keys(IndexScanDesc scan);
-extern bool _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple,
-                         ScanDirection dir, bool *continuescan);
+extern bool _bt_checkkeys(IndexScanDesc scan,
+                                                 Page page, OffsetNumber offnum,
+                                                 ScanDirection dir, bool *continuescan);
 extern BTItem _bt_formitem(IndexTuple itup);
 
 /*