mirror of
https://github.com/postgres/postgres.git
synced 2025-10-22 14:32:25 +03:00
Add support for nearest-neighbor (KNN) searches to SP-GiST
Currently, KNN searches were supported only by GiST. SP-GiST also capable to support them. This commit implements that support. SP-GiST scan stack is replaced with queue, which serves as stack if no ordering is specified. KNN support is provided for three SP-GIST opclasses: quad_point_ops, kd_point_ops and poly_ops (catversion is bumped). Some common parts between GiST and SP-GiST KNNs are extracted into separate functions. Discussion: https://postgr.es/m/570825e8-47d0-4732-2bf6-88d67d2d51c8%40postgrespro.ru Author: Nikita Glukhov, Alexander Korotkov based on GSoC work by Vlad Sterzhanov Review: Andrey Borodin, Alexander Korotkov
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
#include "access/spgist.h"
|
||||
#include "nodes/tidbitmap.h"
|
||||
#include "storage/buf.h"
|
||||
#include "utils/geo_decls.h"
|
||||
#include "utils/relcache.h"
|
||||
|
||||
|
||||
@@ -130,14 +131,35 @@ typedef struct SpGistState
|
||||
bool isBuild; /* true if doing index build */
|
||||
} SpGistState;
|
||||
|
||||
typedef struct SpGistSearchItem
|
||||
{
|
||||
pairingheap_node phNode; /* pairing heap node */
|
||||
Datum value; /* value reconstructed from parent or
|
||||
* leafValue if heaptuple */
|
||||
void *traversalValue; /* opclass-specific traverse value */
|
||||
int level; /* level of items on this page */
|
||||
ItemPointerData heapPtr; /* heap info, if heap tuple */
|
||||
bool isNull; /* SearchItem is NULL item */
|
||||
bool isLeaf; /* SearchItem is heap item */
|
||||
bool recheck; /* qual recheck is needed */
|
||||
bool recheckDistances; /* distance recheck is needed */
|
||||
|
||||
/* array with numberOfOrderBys entries */
|
||||
double distances[FLEXIBLE_ARRAY_MEMBER];
|
||||
} SpGistSearchItem;
|
||||
|
||||
#define SizeOfSpGistSearchItem(n_distances) \
|
||||
(offsetof(SpGistSearchItem, distances) + sizeof(double) * (n_distances))
|
||||
|
||||
/*
|
||||
* Private state of an index scan
|
||||
*/
|
||||
typedef struct SpGistScanOpaqueData
|
||||
{
|
||||
SpGistState state; /* see above */
|
||||
pairingheap *scanQueue; /* queue of to be visited items */
|
||||
MemoryContext tempCxt; /* short-lived memory context */
|
||||
MemoryContext traversalCxt; /* memory context for traversalValues */
|
||||
MemoryContext traversalCxt; /* single scan lifetime memory context */
|
||||
|
||||
/* Control flags showing whether to search nulls and/or non-nulls */
|
||||
bool searchNulls; /* scan matches (all) null entries */
|
||||
@@ -146,9 +168,18 @@ typedef struct SpGistScanOpaqueData
|
||||
/* Index quals to be passed to opclass (null-related quals removed) */
|
||||
int numberOfKeys; /* number of index qualifier conditions */
|
||||
ScanKey keyData; /* array of index qualifier descriptors */
|
||||
int numberOfOrderBys; /* number of ordering operators */
|
||||
ScanKey orderByData; /* array of ordering op descriptors */
|
||||
Oid *orderByTypes; /* array of ordering op return types */
|
||||
Oid indexCollation; /* collation of index column */
|
||||
|
||||
/* Stack of yet-to-be-visited pages */
|
||||
List *scanStack; /* List of ScanStackEntrys */
|
||||
/* Opclass defined functions: */
|
||||
FmgrInfo innerConsistentFn;
|
||||
FmgrInfo leafConsistentFn;
|
||||
|
||||
/* Pre-allocated workspace arrays: */
|
||||
double *zeroDistances;
|
||||
double *infDistances;
|
||||
|
||||
/* These fields are only used in amgetbitmap scans: */
|
||||
TIDBitmap *tbm; /* bitmap being filled */
|
||||
@@ -161,7 +192,10 @@ typedef struct SpGistScanOpaqueData
|
||||
int iPtr; /* index for scanning through same */
|
||||
ItemPointerData heapPtrs[MaxIndexTuplesPerPage]; /* TIDs from cur page */
|
||||
bool recheck[MaxIndexTuplesPerPage]; /* their recheck flags */
|
||||
bool recheckDistances[MaxIndexTuplesPerPage]; /* distance recheck
|
||||
* flags */
|
||||
HeapTuple reconTups[MaxIndexTuplesPerPage]; /* reconstructed tuples */
|
||||
double *distances[MaxIndexTuplesPerPage]; /* distances (for recheck) */
|
||||
|
||||
/*
|
||||
* Note: using MaxIndexTuplesPerPage above is a bit hokey since
|
||||
@@ -410,6 +444,9 @@ extern OffsetNumber SpGistPageAddNewItem(SpGistState *state, Page page,
|
||||
Item item, Size size,
|
||||
OffsetNumber *startOffset,
|
||||
bool errorOK);
|
||||
extern bool spgproperty(Oid index_oid, int attno,
|
||||
IndexAMProperty prop, const char *propname,
|
||||
bool *res, bool *isnull);
|
||||
|
||||
/* spgdoinsert.c */
|
||||
extern void spgUpdateNodeLink(SpGistInnerTuple tup, int nodeN,
|
||||
@@ -421,4 +458,9 @@ extern void spgPageIndexMultiDelete(SpGistState *state, Page page,
|
||||
extern bool spgdoinsert(Relation index, SpGistState *state,
|
||||
ItemPointer heapPtr, Datum datum, bool isnull);
|
||||
|
||||
/* spgproc.c */
|
||||
extern double *spg_key_orderbys_distances(Datum key, bool isLeaf,
|
||||
ScanKey orderbys, int norderbys);
|
||||
extern BOX *box_copy(BOX *orig);
|
||||
|
||||
#endif /* SPGIST_PRIVATE_H */
|
||||
|
Reference in New Issue
Block a user