]> granicus.if.org Git - postgresql/commitdiff
Reduce btree scan overhead for < and > strategies
authorSimon Riggs <simon@2ndQuadrant.com>
Tue, 18 Nov 2014 10:24:55 +0000 (10:24 +0000)
committerSimon Riggs <simon@2ndQuadrant.com>
Tue, 18 Nov 2014 10:24:55 +0000 (10:24 +0000)
For <, <=, > and >= strategies, mark the first scan key
as already matched if scanning in an appropriate direction.
If index tuple contains no nulls we can skip the first
re-check for each tuple.

Author: Rajeev Rastogi
Reviewer: Haribabu Kommi
Rework of the code and comments by Simon Riggs

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

index 203b9691baa2d834d108428482d2e9152d343679..6150b24d02f4d260bb259c703965d40d49244e65 100644 (file)
@@ -996,6 +996,33 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
        if (goback)
                offnum = OffsetNumberPrev(offnum);
 
+       /*
+        * By here the scan position is now set for the first key.  If all
+        * further tuples are expected to match we set the SK_BT_MATCHED flag
+        * to avoid re-checking the scan key later.  This is a big win for
+        * slow key matches though is still significant even for fast datatypes.
+        */
+       switch (startKeys[0]->sk_strategy)
+       {
+               case BTEqualStrategyNumber:
+                       break;
+
+               case BTGreaterEqualStrategyNumber:
+               case BTGreaterStrategyNumber:
+                       if (ScanDirectionIsForward(dir))
+                               startKeys[0]->sk_flags |= SK_BT_MATCHED;
+                       break;
+
+               case BTLessEqualStrategyNumber:
+               case BTLessStrategyNumber:
+                       if (ScanDirectionIsBackward(dir))
+                               startKeys[0]->sk_flags |= SK_BT_MATCHED;
+                       break;
+
+               default:
+                       break;
+       }
+
        /*
         * Now load data from the first page of the scan.
         */
index f8f8e69be7ffe8bdfc24717e045376cc4f0b8b34..a5604679b4a5dceabdbe7b360d18b93c86b06644 100644 (file)
@@ -1429,6 +1429,13 @@ _bt_checkkeys(IndexScanDesc scan,
                bool            isNull;
                Datum           test;
 
+               /*
+                * If the scan key has already matched we can skip this key, as
+                * long as the index tuple does not contain NULL values.
+                */
+               if (key->sk_flags & SK_BT_MATCHED && !IndexTupleHasNulls(tuple))
+                       continue;
+
                /* row-comparison keys need special processing */
                if (key->sk_flags & SK_ROW_HEADER)
                {
index c8bb3f5d668dbd22d94a0866b3baa40eedb58ae2..6ecd2ced62d62bf8b4014a1769636849a57594aa 100644 (file)
@@ -618,6 +618,7 @@ typedef BTScanOpaqueData *BTScanOpaque;
  */
 #define SK_BT_REQFWD   0x00010000              /* required to continue forward scan */
 #define SK_BT_REQBKWD  0x00020000              /* required to continue backward scan */
+#define SK_BT_MATCHED  0x00040000              /* required to skip further key match */
 #define SK_BT_INDOPTION_SHIFT  24              /* must clear the above bits */
 #define SK_BT_DESC                     (INDOPTION_DESC << SK_BT_INDOPTION_SHIFT)
 #define SK_BT_NULLS_FIRST      (INDOPTION_NULLS_FIRST << SK_BT_INDOPTION_SHIFT)