Currently,only the first column of multi-column indices
authorBruce Momjian
Mon, 27 Sep 1999 18:20:21 +0000 (18:20 +0000)
committerBruce Momjian
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)