From 606c0123d627b37d5ac3f7c2c97cd715dde7842f Mon Sep 17 00:00:00 2001 From: Simon Riggs Date: Tue, 18 Nov 2014 10:24:55 +0000 Subject: [PATCH] Reduce btree scan overhead for < and > strategies 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 | 27 +++++++++++++++++++++++++++ src/backend/access/nbtree/nbtutils.c | 7 +++++++ src/include/access/nbtree.h | 1 + 3 files changed, 35 insertions(+) diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c index 203b9691ba..6150b24d02 100644 --- a/src/backend/access/nbtree/nbtsearch.c +++ b/src/backend/access/nbtree/nbtsearch.c @@ -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. */ diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index f8f8e69be7..a5604679b4 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -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) { diff --git a/src/include/access/nbtree.h b/src/include/access/nbtree.h index c8bb3f5d66..6ecd2ced62 100644 --- a/src/include/access/nbtree.h +++ b/src/include/access/nbtree.h @@ -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) -- 2.40.0