mirror of
https://github.com/pgvector/pgvector.git
synced 2026-07-07 13:10:56 +08:00
Improved performance
This commit is contained in:
@@ -612,42 +612,20 @@ GetCandidateDistance(HnswCandidate * hc, Datum q, FmgrInfo *procinfo, Oid collat
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if a candidate is a list member by pointer
|
* Add to visited
|
||||||
*/
|
*/
|
||||||
static bool
|
static inline void
|
||||||
HnswListMemberByPointer(List *v, HnswCandidate * e)
|
AddToVisited(HTAB *v, HnswCandidate * hc, Relation index, bool *found)
|
||||||
{
|
{
|
||||||
ListCell *lc2;
|
if (index == NULL)
|
||||||
|
hash_search(v, &hc->element, HASH_ENTER, found);
|
||||||
foreach(lc2, v)
|
else
|
||||||
{
|
{
|
||||||
HnswCandidate *v2 = (HnswCandidate *) lfirst(lc2);
|
ItemPointerData indextid;
|
||||||
|
|
||||||
if (v2->element == e->element)
|
ItemPointerSet(&indextid, hc->element->blkno, hc->element->offno);
|
||||||
return true;
|
hash_search(v, &indextid, HASH_ENTER, found);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if a candidate is a list member by block and offset
|
|
||||||
*/
|
|
||||||
static bool
|
|
||||||
HnswListMemberByBlock(List *v, HnswCandidate * e)
|
|
||||||
{
|
|
||||||
ListCell *lc2;
|
|
||||||
|
|
||||||
foreach(lc2, v)
|
|
||||||
{
|
|
||||||
HnswCandidate *v2 = (HnswCandidate *) lfirst(lc2);
|
|
||||||
|
|
||||||
/* Neighbor page not set yet */
|
|
||||||
if (v2->element->blkno == e->element->blkno && v2->element->offno == e->element->offno)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -659,17 +637,34 @@ SearchLayer(Datum q, List *ep, int ef, int lc, Relation index, FmgrInfo *procinf
|
|||||||
ListCell *lc2;
|
ListCell *lc2;
|
||||||
|
|
||||||
List *w = NIL;
|
List *w = NIL;
|
||||||
List *v = NIL;
|
|
||||||
pairingheap *C = pairingheap_allocate(CompareNearestCandidates, NULL);
|
pairingheap *C = pairingheap_allocate(CompareNearestCandidates, NULL);
|
||||||
pairingheap *W = pairingheap_allocate(CompareFurthestCandidates, NULL);
|
pairingheap *W = pairingheap_allocate(CompareFurthestCandidates, NULL);
|
||||||
int wlen = 0;
|
int wlen = 0;
|
||||||
|
HASHCTL hash_ctl;
|
||||||
|
HTAB *v;
|
||||||
|
|
||||||
|
/* Create hash table */
|
||||||
|
if (index == NULL)
|
||||||
|
{
|
||||||
|
hash_ctl.keysize = sizeof(HnswElement *);
|
||||||
|
hash_ctl.entrysize = sizeof(HnswElement *);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hash_ctl.keysize = sizeof(ItemPointerData);
|
||||||
|
hash_ctl.entrysize = sizeof(ItemPointerData);
|
||||||
|
}
|
||||||
|
|
||||||
|
hash_ctl.hcxt = CurrentMemoryContext;
|
||||||
|
v = hash_create("hnsw visited", 256, &hash_ctl, HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
|
||||||
|
|
||||||
/* Add entry points to v, C, and W */
|
/* Add entry points to v, C, and W */
|
||||||
foreach(lc2, ep)
|
foreach(lc2, ep)
|
||||||
{
|
{
|
||||||
HnswCandidate *hc = (HnswCandidate *) lfirst(lc2);
|
HnswCandidate *hc = (HnswCandidate *) lfirst(lc2);
|
||||||
|
|
||||||
v = lappend(v, hc);
|
AddToVisited(v, hc, index, NULL);
|
||||||
|
|
||||||
pairingheap_add(C, &(CreatePairingHeapNode(hc)->ph_node));
|
pairingheap_add(C, &(CreatePairingHeapNode(hc)->ph_node));
|
||||||
pairingheap_add(W, &(CreatePairingHeapNode(hc)->ph_node));
|
pairingheap_add(W, &(CreatePairingHeapNode(hc)->ph_node));
|
||||||
|
|
||||||
@@ -696,15 +691,12 @@ SearchLayer(Datum q, List *ep, int ef, int lc, Relation index, FmgrInfo *procinf
|
|||||||
HnswCandidate *e = &neighborhood->items[i];
|
HnswCandidate *e = &neighborhood->items[i];
|
||||||
bool visited;
|
bool visited;
|
||||||
|
|
||||||
/* TODO Use hash for v? */
|
AddToVisited(v, e, index, &visited);
|
||||||
visited = index == NULL ? HnswListMemberByPointer(v, e) : HnswListMemberByBlock(v, e);
|
|
||||||
|
|
||||||
if (!visited)
|
if (!visited)
|
||||||
{
|
{
|
||||||
float eDistance;
|
float eDistance;
|
||||||
|
|
||||||
v = lappend(v, e);
|
|
||||||
|
|
||||||
f = ((HnswPairingHeapNode *) pairingheap_first(W))->inner;
|
f = ((HnswPairingHeapNode *) pairingheap_first(W))->inner;
|
||||||
|
|
||||||
if (index == NULL)
|
if (index == NULL)
|
||||||
|
|||||||
Reference in New Issue
Block a user