Currently,only the first column of multi-column indices
authorBruce Momjian <bruce@momjian.us>
Mon, 27 Sep 1999 18:20:21 +0000 (18:20 +0000)
committerBruce Momjian <bruce@momjian.us>
Mon, 27 Sep 1999 18:20:21 +0000 (18:20 +0000)
is used to find start scan position of Indexscan-s.

To speed up finding scan start position,I have changed
_bt_first() to use as many keys as possible.

I'll attach the patch here.

Regards.

Hiroshi Inoue

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

index 3a5eda3ad8c4e086eaa0d0c82aad4150da85e5dc..0ad8b4ab36f996f5efccfa17e1d0f990e8feb82c 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.53 1999/07/17 20:16:43 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.54 1999/09/27 18:20:21 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -727,11 +727,15 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
        RegProcedure proc;
        int                     result;
        BTScanOpaque so;
-       ScanKeyData skdata;
        Size            keysok;
-       int                     i;
-       int                     nKeyIndex = -1;
 
+       bool            strategyCheck;
+       ScanKey         scankeys = 0;
+       int             keysCount = 0;
+       int             *nKeyIs = 0;
+       int             i, j;
+       StrategyNumber  strat_total;
+       
        rel = scan->relation;
        so = (BTScanOpaque) scan->opaque;
 
@@ -742,38 +746,57 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
        so->numberOfFirstKeys = 0;      /* may be changed by _bt_orderkeys */
        so->qual_ok = 1;                        /* may be changed by _bt_orderkeys */
        scan->scanFromEnd = false;
+       strategyCheck = false;
        if (so->numberOfKeys > 0)
        {
                _bt_orderkeys(rel, so);
 
-               if (ScanDirectionIsBackward(dir))
+               if (so->qual_ok)
+                    strategyCheck = true;
+       }
+       strat_total = BTEqualStrategyNumber;
+       if (strategyCheck)
+       {
+               AttrNumber      attno;
+
+               nKeyIs = (int *)palloc(so->numberOfKeys*sizeof(int));
+               for (i=0; i < so->numberOfKeys; i++)
                {
-                       for (i = 0; i < so->numberOfKeys; i++)
+                       attno = so->keyData[i].sk_attno;
+                       if (attno == keysCount)
+                               continue;
+                       if (attno > keysCount + 1)
+                               break;
+                       strat = _bt_getstrat(rel, attno,
+                                       so->keyData[i].sk_procedure);
+                       if (strat == strat_total ||
+                           strat == BTEqualStrategyNumber)
                        {
-                               if (so->keyData[i].sk_attno != 1)
+                               nKeyIs[keysCount++] = i;
+                               continue;
+                       }
+                       if (ScanDirectionIsBackward(dir) &&
+                           (strat == BTLessStrategyNumber ||
+                            strat == BTLessEqualStrategyNumber) )
+                       {
+                               nKeyIs[keysCount++] = i;
+                               strat_total = strat;
+                               if (strat == BTLessStrategyNumber)
                                        break;
-                               strat = _bt_getstrat(rel, so->keyData[i].sk_attno,
-                                                                        so->keyData[i].sk_procedure);
-                               if (strat == BTLessStrategyNumber ||
-                                       strat == BTLessEqualStrategyNumber ||
-                                       strat == BTEqualStrategyNumber)
-                               {
-                                       nKeyIndex = i;
+                               continue;
+                       }
+                       if (ScanDirectionIsForward(dir) &&
+                           (strat == BTGreaterStrategyNumber ||
+                            strat == BTGreaterEqualStrategyNumber) )
+                       {
+                               nKeyIs[keysCount++] = i;
+                               strat_total = strat;
+                               if (strat == BTGreaterStrategyNumber)
                                        break;
-                               }
+                               continue;
                        }
                }
-               else
-               {
-                       strat = _bt_getstrat(rel, 1, so->keyData[0].sk_procedure);
-
-                       if (strat == BTLessStrategyNumber ||
-                               strat == BTLessEqualStrategyNumber)
-                               ;
-                       else
-                               nKeyIndex = 0;
-               }
-               if (nKeyIndex < 0)
+               if (!keysCount)
                        scan->scanFromEnd = true;
        }
        else
@@ -784,7 +807,11 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 
        /* if we just need to walk down one edge of the tree, do that */
        if (scan->scanFromEnd)
+       {
+               if (nKeyIs)
+                       pfree(nKeyIs);
                return _bt_endpoint(scan, dir);
+       }
 
        itupdesc = RelationGetDescr(rel);
        current = &(scan->currentItemData);
@@ -796,16 +823,24 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
         * at the right place in the scan.
         */
        /* _bt_orderkeys disallows it, but it's place to add some code latter */
-       if (so->keyData[0].sk_flags & SK_ISNULL)
+       scankeys = (ScanKey)palloc(keysCount*sizeof(ScanKeyData));
+       for (i=0; i < keysCount; i++)
        {
-               elog(ERROR, "_bt_first: btree doesn't support is(not)null, yet");
-               return (RetrieveIndexResult) NULL;
+               j = nKeyIs[i];
+               if (so->keyData[j].sk_flags & SK_ISNULL)
+               {
+                       pfree(nKeyIs);
+                       pfree(scankeys);
+                       elog(ERROR, "_bt_first: btree doesn't support is(not)null, yet");
+                       return ((RetrieveIndexResult) NULL);
+               } 
+               proc = index_getprocid(rel, i+1, BTORDER_PROC);
+               ScanKeyEntryInitialize(scankeys+i, so->keyData[j].sk_flags,
+                               i+1, proc, so->keyData[j].sk_argument);
        }
-       proc = index_getprocid(rel, 1, BTORDER_PROC);
-       ScanKeyEntryInitialize(&skdata, so->keyData[nKeyIndex].sk_flags,
-                                                  1, proc, so->keyData[nKeyIndex].sk_argument);
+       if   (nKeyIs)   pfree(nKeyIs);
 
-       stack = _bt_search(rel, 1, &skdata, &buf);
+       stack = _bt_search(rel, keysCount, scankeys, &buf);
        _bt_freestack(stack);
 
        blkno = BufferGetBlockNumber(buf);
@@ -823,6 +858,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
                ItemPointerSetInvalid(current);
                so->btso_curbuf = InvalidBuffer;
                _bt_relbuf(rel, buf, BT_READ);
+               pfree(scankeys);
                return (RetrieveIndexResult) NULL;
        }
        maxoff = PageGetMaxOffsetNumber(page);
@@ -835,7 +871,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
         */
 
        while (maxoff == P_HIKEY && !P_RIGHTMOST(pop) &&
-                  _bt_skeycmp(rel, 1, &skdata, page,
+                  _bt_skeycmp(rel, keysCount, scankeys, page,
                                           PageGetItemId(page, P_HIKEY),
                                           BTGreaterEqualStrategyNumber))
        {
@@ -849,6 +885,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
                        ItemPointerSetInvalid(current);
                        so->btso_curbuf = InvalidBuffer;
                        _bt_relbuf(rel, buf, BT_READ);
+                       pfree(scankeys);
                        return (RetrieveIndexResult) NULL;
                }
                maxoff = PageGetMaxOffsetNumber(page);
@@ -857,7 +894,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 
 
        /* find the nearest match to the manufactured scan key on the page */
-       offnum = _bt_binsrch(rel, buf, 1, &skdata, BT_DESCENT);
+       offnum = _bt_binsrch(rel, buf, keysCount, scankeys, BT_DESCENT);
 
        if (offnum > maxoff)
        {
@@ -872,12 +909,11 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
         * we're looking for minus the value we're looking at in the index.
         */
 
-       result = _bt_compare(rel, itupdesc, page, 1, &skdata, offnum);
+       result = _bt_compare(rel, itupdesc, page, keysCount, scankeys, offnum);
 
        /* it's yet other place to add some code latter for is(not)null */
 
-       strat = _bt_getstrat(rel, 1, so->keyData[nKeyIndex].sk_procedure);
-
+       strat = strat_total;
        switch (strat)
        {
                case BTLessStrategyNumber:
@@ -890,7 +926,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 
                                        offnum = ItemPointerGetOffsetNumber(current);
                                        page = BufferGetPage(buf);
-                                       result = _bt_compare(rel, itupdesc, page, 1, &skdata, offnum);
+                                       result = _bt_compare(rel, itupdesc, page, keysCount, scankeys, offnum);
                                } while (result <= 0);
 
                        }
@@ -906,12 +942,11 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 
                                        offnum = ItemPointerGetOffsetNumber(current);
                                        page = BufferGetPage(buf);
-                                       result = _bt_compare(rel, itupdesc, page, 1, &skdata, offnum);
+                                       result = _bt_compare(rel, itupdesc, page, keysCount, scankeys, offnum);
                                } while (result >= 0);
-
-                               if (result < 0)
-                                       _bt_twostep(scan, &buf, BackwardScanDirection);
                        }
+                       if (result < 0)
+                               _bt_twostep(scan, &buf, BackwardScanDirection);
                        break;
 
                case BTEqualStrategyNumber:
@@ -920,6 +955,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
                                _bt_relbuf(scan->relation, buf, BT_READ);
                                so->btso_curbuf = InvalidBuffer;
                                ItemPointerSetInvalid(&(scan->currentItemData));
+                               pfree(scankeys);
                                return (RetrieveIndexResult) NULL;
                        }
                        else if (ScanDirectionIsBackward(dir))
@@ -931,7 +967,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 
                                        offnum = ItemPointerGetOffsetNumber(current);
                                        page = BufferGetPage(buf);
-                                       result = _bt_compare(rel, itupdesc, page, 1, &skdata, offnum);
+                                       result = _bt_compare(rel, itupdesc, page, keysCount, scankeys, offnum);
                                } while (result == 0);
 
                                if (result < 0)
@@ -950,6 +986,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
                                                _bt_relbuf(scan->relation, buf, BT_READ);
                                                so->btso_curbuf = InvalidBuffer;
                                                ItemPointerSetInvalid(&(scan->currentItemData));
+                                               pfree(scankeys);
                                                return (RetrieveIndexResult) NULL;
                                        }
                                }
@@ -974,7 +1011,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 
                                        page = BufferGetPage(buf);
                                        offnum = ItemPointerGetOffsetNumber(current);
-                                       result = _bt_compare(rel, itupdesc, page, 1, &skdata, offnum);
+                                       result = _bt_compare(rel, itupdesc, page, keysCount, scankeys, offnum);
                                } while (result < 0);
 
                                if (result > 0)
@@ -993,12 +1030,13 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 
                                        offnum = ItemPointerGetOffsetNumber(current);
                                        page = BufferGetPage(buf);
-                                       result = _bt_compare(rel, itupdesc, page, 1, &skdata, offnum);
+                                       result = _bt_compare(rel, itupdesc, page, keysCount, scankeys, offnum);
                                } while (result >= 0);
                        }
                        break;
        }
 
+       pfree(scankeys);
        /* okay, current item pointer for the scan is right */
        offnum = ItemPointerGetOffsetNumber(current);
        page = BufferGetPage(buf);
index 2a5e7578d2f196888b7b0b5bcba61f93448a7f8b..ee0cd1483b4279670ee082b2dc1b0e747a51e775 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.32 1999/07/17 20:16:43 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.33 1999/09/27 18:20:21 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -101,6 +101,7 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
        uint16          numberOfKeys = so->numberOfKeys;
        uint16          new_numberOfKeys = 0;
        AttrNumber      attno = 1;
+       bool            equalStrategyEnd, underEqualStrategy;
 
        if (numberOfKeys < 1)
                return;
@@ -136,6 +137,8 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
        for (j = 0; j <= BTMaxStrategyNumber; j++)
                init[j] = 0;
 
+       equalStrategyEnd = false;
+       underEqualStrategy = true;
        /* check each key passed in */
        for (i = 0;;)
        {
@@ -150,6 +153,7 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
                        if (cur->sk_attno != attno + 1 && i < numberOfKeys)
                                elog(ERROR, "_bt_orderkeys: key(s) for attribute %d missed", attno + 1);
 
+                       underEqualStrategy = (!equalStrategyEnd);
                        /*
                         * If = has been specified, no other key will be used. In case
                         * of key < 2 && key == 1 and so on we have to set qual_ok to
@@ -175,6 +179,8 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
                                init[BTGreaterEqualStrategyNumber - 1] = 0;
                                init[BTGreaterStrategyNumber - 1] = 0;
                        }
+                       else
+                               equalStrategyEnd = true;
 
                        /* only one of <, <= */
                        if (init[BTLessStrategyNumber - 1]
@@ -223,7 +229,7 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
                                if (init[j])
                                        key[new_numberOfKeys++] = xform[j];
 
-                       if (attno == 1)
+                       if (underEqualStrategy)
                                so->numberOfFirstKeys = new_numberOfKeys;
 
                        if (i == numberOfKeys)