mirror of
https://github.com/postgres/postgres.git
synced 2025-10-25 13:17:41 +03:00
Speed up "rare & frequent" type GIN queries.
If you have a GIN query like "rare & frequent", we currently fetch all the items that match either rare or frequent, call the consistent function for each item, and let the consistent function filter out items that only match one of the terms. However, if we can deduce that "rare" must be present for the overall qual to be true, we can scan all the rare items, and for each rare item, skip over to the next frequent item with the same or greater TID. That greatly speeds up "rare & frequent" type queries. To implement that, introduce the concept of a tri-state consistent function, where the 3rd value is MAYBE, indicating that we don't know if that term is present. Operator classes only provide a boolean consistent function, so we simulate the tri-state consistent function by calling the boolean function several times, with the MAYBE arguments set to all combinations of TRUE and FALSE. Testing all combinations is only feasible for a small number of MAYBE arguments, but it is envisioned that we'll provide a way for operator classes to provide a native tri-state consistent function, which can be much more efficient. But that is not included in this patch. We were already using that trick to for lossy pages, calling the consistent function with the lossy entry set to TRUE and FALSE. Now that we have the tri-state consistent function, use it for lossy pages too. Alexander Korotkov, with fair amount of refactoring by me.
This commit is contained in:
@@ -746,8 +746,25 @@ typedef struct GinScanKeyData
|
||||
/* array of GinScanEntry pointers, one per extracted search condition */
|
||||
GinScanEntry *scanEntry;
|
||||
|
||||
/*
|
||||
* At least one of the entries in requiredEntries must be present for
|
||||
* a tuple to match the overall qual.
|
||||
*
|
||||
* additionalEntries contains entries that are needed by the consistent
|
||||
* function to decide if an item matches, but are not sufficient to
|
||||
* satisfy the qual without entries from requiredEntries.
|
||||
*/
|
||||
GinScanEntry *requiredEntries;
|
||||
int nrequired;
|
||||
GinScanEntry *additionalEntries;
|
||||
int nadditional;
|
||||
|
||||
/* array of check flags, reported to consistentFn */
|
||||
bool *entryRes;
|
||||
bool (*boolConsistentFn) (GinScanKey key);
|
||||
bool (*triConsistentFn) (GinScanKey key);
|
||||
FmgrInfo *consistentFmgrInfo;
|
||||
Oid collation;
|
||||
|
||||
/* other data needed for calling consistentFn */
|
||||
Datum query;
|
||||
@@ -832,6 +849,20 @@ extern void ginNewScanKey(IndexScanDesc scan);
|
||||
/* ginget.c */
|
||||
extern Datum gingetbitmap(PG_FUNCTION_ARGS);
|
||||
|
||||
/* ginlogic.c */
|
||||
|
||||
enum
|
||||
{
|
||||
GIN_FALSE = 0, /* item is present / matches */
|
||||
GIN_TRUE = 1, /* item is not present / does not match */
|
||||
GIN_MAYBE = 2 /* don't know if item is present / don't know if
|
||||
* matches */
|
||||
} GinLogicValueEnum;
|
||||
|
||||
typedef char GinLogicValue;
|
||||
|
||||
extern void ginInitConsistentFunction(GinState *ginstate, GinScanKey key);
|
||||
|
||||
/* ginvacuum.c */
|
||||
extern Datum ginbulkdelete(PG_FUNCTION_ARGS);
|
||||
extern Datum ginvacuumcleanup(PG_FUNCTION_ARGS);
|
||||
|
||||
Reference in New Issue
Block a user