From 6fc50a6a405b8232a935a3d2459b62dec09c570c Mon Sep 17 00:00:00 2001 From: Dmitrii Dolgov <9erthalion6@gmail.com> Date: Sat, 22 Jan 2022 21:13:42 +0100 Subject: [PATCH v41 5/6] Extend index skip scan with ScanLooseKey Index skip scan relies on the information about key prefix that needs to be jumped over, but it's represented in a rather limited fashion only via the prefix size. This approach is sufficient now, but for the sake of flexibility introduce a concept of ScanLooseKey to represent underspecified search keys. At the moment it's inspired by the idea of skip keys constrained in some range of keyspace, and not used in any way. --- src/backend/executor/nodeIndexonlyscan.c | 14 ++++++++++---- src/include/access/relscan.h | 2 ++ src/include/access/skey.h | 8 ++++++++ src/include/nodes/execnodes.h | 5 ++++- 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c index d5abac20cb..470c364e53 100644 --- a/src/backend/executor/nodeIndexonlyscan.c +++ b/src/backend/executor/nodeIndexonlyscan.c @@ -147,12 +147,12 @@ IndexOnlyNext(IndexOnlyScanState *node) * Due to that we skip also when the first tuple wasn't emitted yet, but * the directions are opposite. */ - if (node->ioss_SkipPrefixSize > 0 && + if (node->ioss_ScanLooseKeys != NULL && (node->ioss_FirstTupleEmitted || ScanDirectionsAreOpposite(direction, indexonlyscan->indexorderdir))) { if (!index_skip(scandesc, direction, indexonlyscan->indexorderdir, - !node->ioss_FirstTupleEmitted, node->ioss_SkipPrefixSize)) + !node->ioss_FirstTupleEmitted, node->ioss_NumScanLooseKeys)) { /* * Reached end of index. At this point currPos is invalidated, and @@ -202,7 +202,7 @@ IndexOnlyNext(IndexOnlyScanState *node) if (!index_skip(scandesc, direction, indexonlyscan->indexorderdir, !node->ioss_FirstTupleEmitted, - node->ioss_SkipPrefixSize)) + node->ioss_NumScanLooseKeys)) { node->ioss_FirstTupleEmitted = false; return ExecClearTuple(slot); @@ -594,7 +594,6 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags) indexstate->ss.ps.plan = (Plan *) node; indexstate->ss.ps.state = estate; indexstate->ss.ps.ExecProcNode = ExecIndexOnlyScan; - indexstate->ioss_SkipPrefixSize = node->indexskipprefixsize; indexstate->ioss_FirstTupleEmitted = false; /* @@ -697,6 +696,13 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags) NULL, /* no ArrayKeys */ NULL); + if (node->indexskipprefixsize != 0) + { + indexstate->ioss_NumScanLooseKeys = node->indexskipprefixsize; + indexstate->ioss_ScanLooseKeys = + (ScanLooseKey) palloc(node->indexskipprefixsize * sizeof(ScanLooseKeyData)); + } + /* * If we have runtime keys, we need an ExprContext to evaluate them. The * node's standard context won't do because we want to reset that context diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h index 53a93ccbe7..5200a1867d 100644 --- a/src/include/access/relscan.h +++ b/src/include/access/relscan.h @@ -119,8 +119,10 @@ typedef struct IndexScanDescData struct SnapshotData *xs_snapshot; /* snapshot to see */ int numberOfKeys; /* number of index qualifier conditions */ int numberOfOrderBys; /* number of ordering operators */ + int numberOfLooseKeys; /* number of loose index qualifier conditions */ struct ScanKeyData *keyData; /* array of index qualifier descriptors */ struct ScanKeyData *orderByData; /* array of ordering op descriptors */ + struct ScanLooseKeyData *looseKeyData; /* array of loose index qualifier descriptors */ bool xs_want_itup; /* caller requests index tuples */ bool xs_temp_snap; /* unregister snapshot at scan end? */ diff --git a/src/include/access/skey.h b/src/include/access/skey.h index b5ab17f7d9..a711dc353d 100644 --- a/src/include/access/skey.h +++ b/src/include/access/skey.h @@ -74,6 +74,14 @@ typedef struct ScanKeyData typedef ScanKeyData *ScanKey; +typedef struct ScanLooseKeyData +{ + ScanKey start; + ScanKey end; +} ScanLooseKeyData; + +typedef ScanLooseKeyData *ScanLooseKey; + /* * About row comparisons: * diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index cf36e6c0e6..fa6ee25bc6 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -1508,6 +1508,8 @@ typedef struct IndexScanState * NumOrderByKeys number of OrderByKeys * RuntimeKeys info about Skeys that must be evaluated at runtime * NumRuntimeKeys number of RuntimeKeys + * ScanLooseKeys Skey structures for loose index quals + * NumScanLooseKeys number of ScanLooseKeys * RuntimeKeysReady true if runtime Skeys have been computed * RuntimeContext expr context for evaling runtime Skeys * RelationDesc index relation descriptor @@ -1527,13 +1529,14 @@ typedef struct IndexOnlyScanState int ioss_NumOrderByKeys; IndexRuntimeKeyInfo *ioss_RuntimeKeys; int ioss_NumRuntimeKeys; + struct ScanLooseKeyData *ioss_ScanLooseKeys; + int ioss_NumScanLooseKeys; bool ioss_RuntimeKeysReady; ExprContext *ioss_RuntimeContext; Relation ioss_RelationDesc; struct IndexScanDescData *ioss_ScanDesc; TupleTableSlot *ioss_TableSlot; Buffer ioss_VMBuffer; - int ioss_SkipPrefixSize; bool ioss_FirstTupleEmitted; Size ioss_PscanLen; } IndexOnlyScanState; -- 2.32.0