1
0
mirror of https://github.com/pgvector/pgvector.git synced 2026-10-23 10:48:54 +03:00

Added support [skip ci]

This commit is contained in:
Andrew Kane
2026-10-05 19:34:36 -07:00
parent 981f9a372e
commit 1db5e63af2
3 changed files with 18 additions and 15 deletions

View File

@@ -410,6 +410,7 @@ typedef union
typedef struct HnswSearchState
{
HnswQuery q;
HnswSupport *support;
} HnswSearchState;
typedef struct HnswScanOpaqueData
@@ -468,14 +469,14 @@ bool HnswCheckNorm(HnswSupport * support, Datum value);
Buffer HnswNewBuffer(Relation index, ForkNumber forkNum);
void HnswInitPage(Buffer buf, Page page);
void HnswInit(void);
List *HnswSearchLayer(char *base, HnswSearchState * searchState, List *ep, int ef, int lc, Relation index, HnswSupport * support, int m, bool inserting, HnswElement skipElement, visited_hash * v, pairingheap **discarded, bool initVisited, int64 *tuples);
List *HnswSearchLayer(char *base, HnswSearchState * searchState, List *ep, int ef, int lc, Relation index, int m, bool inserting, HnswElement skipElement, visited_hash * v, pairingheap **discarded, bool initVisited, int64 *tuples);
HnswElement HnswGetEntryPoint(Relation index);
void HnswGetMetaPageInfo(Relation index, int *m, int *dimensions, HnswElement * entryPoint);
void *HnswAlloc(HnswAllocator * allocator, Size size);
HnswElement HnswInitElement(char *base, ItemPointer tid, int m, double ml, int maxLevel, HnswAllocator * alloc);
HnswElement HnswInitElementFromBlock(BlockNumber blkno, OffsetNumber offno);
void HnswFindElementNeighbors(char *base, HnswElement element, HnswElement entryPoint, Relation index, HnswSupport * support, int m, int efConstruction, bool existing);
HnswSearchCandidate *HnswEntryCandidate(char *base, HnswElement entryPoint, HnswSearchState * searchState, Relation index, HnswSupport * support, bool loadVec);
HnswSearchCandidate *HnswEntryCandidate(char *base, HnswElement entryPoint, HnswSearchState * searchState, Relation index, bool loadVec);
void HnswUpdateMetaPage(Relation index, int updateEntry, HnswElement entryPoint, BlockNumber insertPage, ForkNumber forkNum, bool building);
void HnswSetNeighborTuple(char *base, HnswNeighborTuple ntup, HnswElement e, int m);
void HnswAddHeapTid(HnswElement element, ItemPointer heaptid);

View File

@@ -44,20 +44,21 @@ GetScanItems(IndexScanDesc scan, Datum value)
HnswCheckDim(dimensions, so->typeInfo, support->collation, value);
searchState->q.value = value;
searchState->support = support;
so->m = m;
if (entryPoint == NULL)
return NIL;
ep = list_make1(HnswEntryCandidate(base, entryPoint, searchState, index, support, false));
ep = list_make1(HnswEntryCandidate(base, entryPoint, searchState, index, false));
for (int lc = entryPoint->level; lc >= 1; lc--)
{
w = HnswSearchLayer(base, searchState, ep, 1, lc, index, support, m, false, NULL, NULL, NULL, true, NULL);
w = HnswSearchLayer(base, searchState, ep, 1, lc, index, m, false, NULL, NULL, NULL, true, NULL);
ep = w;
}
return HnswSearchLayer(base, searchState, ep, hnsw_ef_search, 0, index, support, m, false, NULL, &so->v, hnsw_iterative_scan != HNSW_ITERATIVE_SCAN_OFF ? &so->discarded : NULL, true, &so->tuples);
return HnswSearchLayer(base, searchState, ep, hnsw_ef_search, 0, index, m, false, NULL, &so->v, hnsw_iterative_scan != HNSW_ITERATIVE_SCAN_OFF ? &so->discarded : NULL, true, &so->tuples);
}
/*
@@ -88,7 +89,7 @@ ResumeScanItems(IndexScanDesc scan)
ep = lappend(ep, sc);
}
return HnswSearchLayer(base, &so->searchState, ep, batch_size, 0, index, &so->support, so->m, false, NULL, &so->v, &so->discarded, false, &so->tuples);
return HnswSearchLayer(base, &so->searchState, ep, batch_size, 0, index, so->m, false, NULL, &so->v, &so->discarded, false, &so->tuples);
}
/*

View File

@@ -612,15 +612,15 @@ HnswInitSearchCandidate(char *base, HnswElement element, double distance)
* Create a candidate for the entry point
*/
HnswSearchCandidate *
HnswEntryCandidate(char *base, HnswElement entryPoint, HnswSearchState * searchState, Relation index, HnswSupport * support, bool loadVec)
HnswEntryCandidate(char *base, HnswElement entryPoint, HnswSearchState * searchState, Relation index, bool loadVec)
{
bool inMemory = index == NULL;
double distance;
if (inMemory)
distance = GetElementDistance(base, entryPoint, &searchState->q, support);
distance = GetElementDistance(base, entryPoint, &searchState->q, searchState->support);
else
HnswLoadElement(entryPoint, &distance, &searchState->q, index, support, loadVec, NULL);
HnswLoadElement(entryPoint, &distance, &searchState->q, index, searchState->support, loadVec, NULL);
return HnswInitSearchCandidate(base, entryPoint, distance);
}
@@ -825,7 +825,7 @@ HnswLoadUnvisitedFromDisk(HnswElement element, HnswUnvisited * unvisited, int *u
* Algorithm 2 from paper
*/
List *
HnswSearchLayer(char *base, HnswSearchState * searchState, List *ep, int ef, int lc, Relation index, HnswSupport * support, int m, bool inserting, HnswElement skipElement, visited_hash * v, pairingheap **discarded, bool initVisited, int64 *tuples)
HnswSearchLayer(char *base, HnswSearchState * searchState, List *ep, int ef, int lc, Relation index, int m, bool inserting, HnswElement skipElement, visited_hash * v, pairingheap **discarded, bool initVisited, int64 *tuples)
{
List *w = NIL;
pairingheap *C = pairingheap_allocate(CompareNearestCandidates, NULL);
@@ -920,7 +920,7 @@ HnswSearchLayer(char *base, HnswSearchState * searchState, List *ep, int ef, int
if (inMemory)
{
eElement = unvisited[i].element;
eDistance = GetElementDistance(base, eElement, &searchState->q, support);
eDistance = GetElementDistance(base, eElement, &searchState->q, searchState->support);
}
else
{
@@ -930,7 +930,7 @@ HnswSearchLayer(char *base, HnswSearchState * searchState, List *ep, int ef, int
/* Avoid any allocations if not adding */
eElement = NULL;
HnswLoadElementImpl(blkno, offno, &eDistance, &searchState->q, index, support, inserting, alwaysAdd || discarded != NULL ? NULL : &f->distance, &eElement);
HnswLoadElementImpl(blkno, offno, &eDistance, &searchState->q, index, searchState->support, inserting, alwaysAdd || discarded != NULL ? NULL : &f->distance, &eElement);
if (eElement == NULL)
continue;
@@ -1292,6 +1292,7 @@ HnswFindElementNeighbors(char *base, HnswElement element, HnswElement entryPoint
bool inMemory = index == NULL;
searchState.q.value = HnswGetValue(base, element);
searchState.support = support;
/* Precompute hash */
if (inMemory)
@@ -1302,13 +1303,13 @@ HnswFindElementNeighbors(char *base, HnswElement element, HnswElement entryPoint
return;
/* Get entry point and level */
ep = list_make1(HnswEntryCandidate(base, entryPoint, &searchState, index, support, true));
ep = list_make1(HnswEntryCandidate(base, entryPoint, &searchState, index, true));
entryLevel = entryPoint->level;
/* 1st phase: greedy search to insert level */
for (int lc = entryLevel; lc >= level + 1; lc--)
{
w = HnswSearchLayer(base, &searchState, ep, 1, lc, index, support, m, true, skipElement, NULL, NULL, true, NULL);
w = HnswSearchLayer(base, &searchState, ep, 1, lc, index, m, true, skipElement, NULL, NULL, true, NULL);
ep = w;
}
@@ -1327,7 +1328,7 @@ HnswFindElementNeighbors(char *base, HnswElement element, HnswElement entryPoint
List *lw = NIL;
ListCell *lc2;
w = HnswSearchLayer(base, &searchState, ep, efConstruction, lc, index, support, m, true, skipElement, NULL, NULL, true, NULL);
w = HnswSearchLayer(base, &searchState, ep, efConstruction, lc, index, m, true, skipElement, NULL, NULL, true, NULL);
/* Convert search candidates to candidates */
foreach(lc2, w)