Commit 56a57473 authored by Tom Lane's avatar Tom Lane

Refactor GIN's handling of duplicate search entries.

The original coding could combine duplicate entries only when they
originated from the same qual condition.  In particular it could not
combine cases where multiple qual conditions all give rise to full-index
scan requests, which is an expensive case well worth optimizing.  Refactor
so that duplicates are recognized across all the quals.
parent 002c105a
This diff is collapsed.
This diff is collapsed.
...@@ -549,12 +549,19 @@ extern void ginPrepareDataScan(GinBtree btree, Relation index); ...@@ -549,12 +549,19 @@ extern void ginPrepareDataScan(GinBtree btree, Relation index);
/* ginscan.c */ /* ginscan.c */
/* /*
* GinScanKeyData describes a single GIN index qualification condition. * GinScanKeyData describes a single GIN index qualifier expression.
* It contains one GinScanEntryData for each key datum extracted from *
* the qual by the extractQueryFn or added implicitly by ginFillScanKey. * From each qual expression, we extract one or more specific index search
* nentries is the true number of entries, nuserentries is the number * conditions, which are represented by GinScanEntryData. It's quite
* that extractQueryFn returned (which is what we report to consistentFn). * possible for identical search conditions to be requested by more than
* The "user" entries must come first. * one qual expression, in which case we merge such conditions to have just
* one unique GinScanEntry --- this is particularly important for efficiency
* when dealing with full-index-scan entries. So there can be multiple
* GinScanKeyData.scanEntry pointers to the same GinScanEntryData.
*
* In each GinScanKeyData, nentries is the true number of entries, while
* nuserentries is the number that extractQueryFn returned (which is what
* we report to consistentFn). The "user" entries must come first.
*/ */
typedef struct GinScanKeyData *GinScanKey; typedef struct GinScanKeyData *GinScanKey;
...@@ -567,10 +574,10 @@ typedef struct GinScanKeyData ...@@ -567,10 +574,10 @@ typedef struct GinScanKeyData
/* Number of entries that extractQueryFn and consistentFn know about */ /* Number of entries that extractQueryFn and consistentFn know about */
uint32 nuserentries; uint32 nuserentries;
/* array of GinScanEntryData, one per key datum */ /* array of GinScanEntry pointers, one per extracted search condition */
GinScanEntry scanEntry; GinScanEntry *scanEntry;
/* array of ItemPointer result, reported to consistentFn */ /* array of check flags, reported to consistentFn */
bool *entryRes; bool *entryRes;
/* other data needed for calling consistentFn */ /* other data needed for calling consistentFn */
...@@ -583,22 +590,21 @@ typedef struct GinScanKeyData ...@@ -583,22 +590,21 @@ typedef struct GinScanKeyData
int32 searchMode; int32 searchMode;
OffsetNumber attnum; OffsetNumber attnum;
/* scan status data */ /*
* Match status data. curItem is the TID most recently tested (could be
* a lossy-page pointer). curItemMatches is TRUE if it passes the
* consistentFn test; if so, recheckCurItem is the recheck flag.
* isFinished means that all the input entry streams are finished, so
* this key cannot succeed for any later TIDs.
*/
ItemPointerData curItem; ItemPointerData curItem;
bool curItemMatches;
bool recheckCurItem; bool recheckCurItem;
bool firstCall;
bool isFinished; bool isFinished;
} GinScanKeyData; } GinScanKeyData;
typedef struct GinScanEntryData typedef struct GinScanEntryData
{ {
/* link to any preceding identical entry in current scan key */
GinScanEntry master;
/* ptr to value reported to consistentFn, points to parent->entryRes[i] */
bool *pval;
/* query key and other information from extractQueryFn */ /* query key and other information from extractQueryFn */
Datum queryKey; Datum queryKey;
GinNullCategory queryCategory; GinNullCategory queryCategory;
...@@ -634,10 +640,14 @@ typedef struct GinScanOpaqueData ...@@ -634,10 +640,14 @@ typedef struct GinScanOpaqueData
MemoryContext tempCtx; MemoryContext tempCtx;
GinState ginstate; GinState ginstate;
GinScanKey keys; GinScanKey keys; /* one per scan qualifier expr */
uint32 nkeys; uint32 nkeys;
bool isVoidRes; /* true if ginstate.extractQueryFn guarantees
* that nothing will be found */ GinScanEntry *entries; /* one per index search condition */
uint32 totalentries;
uint32 allocentries; /* allocated length of entries[] */
bool isVoidRes; /* true if query is unsatisfiable */
} GinScanOpaqueData; } GinScanOpaqueData;
typedef GinScanOpaqueData *GinScanOpaque; typedef GinScanOpaqueData *GinScanOpaque;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment