mirror of
https://github.com/pgvector/pgvector.git
synced 2026-07-13 08:06:54 +08:00
Removed distance from neighbor tuples
This commit is contained in:
13
src/hnsw.h
13
src/hnsw.h
@@ -49,7 +49,7 @@
|
|||||||
#define PROGRESS_HNSW_PHASE_LOAD 2
|
#define PROGRESS_HNSW_PHASE_LOAD 2
|
||||||
|
|
||||||
#define HNSW_ELEMENT_TUPLE_SIZE(_dim) MAXALIGN(offsetof(HnswElementTupleData, vec) + VECTOR_SIZE(_dim))
|
#define HNSW_ELEMENT_TUPLE_SIZE(_dim) MAXALIGN(offsetof(HnswElementTupleData, vec) + VECTOR_SIZE(_dim))
|
||||||
#define HNSW_NEIGHBOR_TUPLE_SIZE(level, m) MAXALIGN(offsetof(HnswNeighborTupleData, neighbors) + ((level) + 2) * (m) * sizeof(HnswNeighborTupleItem))
|
#define HNSW_NEIGHBOR_TUPLE_SIZE(level, m) MAXALIGN(offsetof(HnswNeighborTupleData, indextids) + ((level) + 2) * (m) * sizeof(ItemPointerData))
|
||||||
|
|
||||||
#define HnswPageGetOpaque(page) ((HnswPageOpaque) PageGetSpecialPointer(page))
|
#define HnswPageGetOpaque(page) ((HnswPageOpaque) PageGetSpecialPointer(page))
|
||||||
#define HnswPageGetMeta(page) ((HnswMetaPageData *) PageGetContents(page))
|
#define HnswPageGetMeta(page) ((HnswMetaPageData *) PageGetContents(page))
|
||||||
@@ -197,19 +197,12 @@ typedef struct HnswElementTupleData
|
|||||||
|
|
||||||
typedef HnswElementTupleData * HnswElementTuple;
|
typedef HnswElementTupleData * HnswElementTuple;
|
||||||
|
|
||||||
typedef struct HnswNeighborTupleItem
|
|
||||||
{
|
|
||||||
ItemPointerData indextid;
|
|
||||||
uint16 unused;
|
|
||||||
float distance; /* improves performance of inserts */
|
|
||||||
} HnswNeighborTupleItem;
|
|
||||||
|
|
||||||
typedef struct HnswNeighborTupleData
|
typedef struct HnswNeighborTupleData
|
||||||
{
|
{
|
||||||
uint8 type;
|
uint8 type;
|
||||||
uint8 unused;
|
uint8 unused;
|
||||||
uint16 count;
|
uint16 count;
|
||||||
HnswNeighborTupleItem neighbors[FLEXIBLE_ARRAY_MEMBER];
|
ItemPointerData indextids[FLEXIBLE_ARRAY_MEMBER];
|
||||||
} HnswNeighborTupleData;
|
} HnswNeighborTupleData;
|
||||||
|
|
||||||
typedef HnswNeighborTupleData * HnswNeighborTuple;
|
typedef HnswNeighborTupleData * HnswNeighborTuple;
|
||||||
@@ -296,6 +289,6 @@ bool hnswgettuple(IndexScanDesc scan, ScanDirection dir);
|
|||||||
void hnswendscan(IndexScanDesc scan);
|
void hnswendscan(IndexScanDesc scan);
|
||||||
|
|
||||||
/* Ensure fits in uint8 */
|
/* Ensure fits in uint8 */
|
||||||
#define HnswGetMaxLevel(m) Min(((BLCKSZ - MAXALIGN(SizeOfPageHeaderData) - MAXALIGN(sizeof(HnswPageOpaqueData)) - offsetof(HnswNeighborTupleData, neighbors) - sizeof(ItemIdData)) / (sizeof(HnswNeighborTupleItem)) / m) - 2, 255)
|
#define HnswGetMaxLevel(m) Min(((BLCKSZ - MAXALIGN(SizeOfPageHeaderData) - MAXALIGN(sizeof(HnswPageOpaqueData)) - offsetof(HnswNeighborTupleData, indextids) - sizeof(ItemIdData)) / (sizeof(ItemPointerData)) / m) - 2, 255)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -317,11 +317,10 @@ UpdateNeighborPages(Relation index, HnswElement e, int m, List *updates)
|
|||||||
/* Make robust to issues */
|
/* Make robust to issues */
|
||||||
if (idx < ntup->count)
|
if (idx < ntup->count)
|
||||||
{
|
{
|
||||||
HnswNeighborTupleItem *neighbor = &ntup->neighbors[idx];
|
ItemPointer indextid = &ntup->indextids[idx];
|
||||||
|
|
||||||
/* Update neighbor */
|
/* Update neighbor */
|
||||||
ItemPointerSet(&neighbor->indextid, e->blkno, e->offno);
|
ItemPointerSet(indextid, e->blkno, e->offno);
|
||||||
neighbor->distance = update->hc.distance;
|
|
||||||
|
|
||||||
/* Overwrite tuple */
|
/* Overwrite tuple */
|
||||||
if (!PageIndexTupleOverwrite(page, offno, (Item) ntup, ntupSize))
|
if (!PageIndexTupleOverwrite(page, offno, (Item) ntup, ntupSize))
|
||||||
|
|||||||
@@ -309,20 +309,16 @@ HnswSetNeighborTuple(HnswNeighborTuple ntup, HnswElement e, int m)
|
|||||||
|
|
||||||
for (int i = 0; i < lm; i++)
|
for (int i = 0; i < lm; i++)
|
||||||
{
|
{
|
||||||
HnswNeighborTupleItem *neighbor = &ntup->neighbors[idx++];
|
ItemPointer indextid = &ntup->indextids[idx++];
|
||||||
|
|
||||||
if (i < neighbors->length)
|
if (i < neighbors->length)
|
||||||
{
|
{
|
||||||
HnswCandidate *hc = &neighbors->items[i];
|
HnswCandidate *hc = &neighbors->items[i];
|
||||||
|
|
||||||
ItemPointerSet(&neighbor->indextid, hc->element->blkno, hc->element->offno);
|
ItemPointerSet(indextid, hc->element->blkno, hc->element->offno);
|
||||||
neighbor->distance = hc->distance;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
ItemPointerSetInvalid(indextid);
|
||||||
ItemPointerSetInvalid(&neighbor->indextid);
|
|
||||||
neighbor->distance = NAN;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,15 +348,15 @@ LoadNeighborsFromPage(HnswElement element, Relation index, Page page)
|
|||||||
HnswElement e;
|
HnswElement e;
|
||||||
int level;
|
int level;
|
||||||
HnswCandidate *hc;
|
HnswCandidate *hc;
|
||||||
HnswNeighborTupleItem *neighbor;
|
ItemPointer indextid;
|
||||||
HnswNeighborArray *neighbors;
|
HnswNeighborArray *neighbors;
|
||||||
|
|
||||||
neighbor = &ntup->neighbors[i];
|
indextid = &ntup->indextids[i];
|
||||||
|
|
||||||
if (!ItemPointerIsValid(&neighbor->indextid))
|
if (!ItemPointerIsValid(indextid))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
e = InitElementFromBlock(ItemPointerGetBlockNumber(&neighbor->indextid), ItemPointerGetOffsetNumber(&neighbor->indextid));
|
e = InitElementFromBlock(ItemPointerGetBlockNumber(indextid), ItemPointerGetOffsetNumber(indextid));
|
||||||
|
|
||||||
/* Calculate level based on offset */
|
/* Calculate level based on offset */
|
||||||
level = element->level - i / m;
|
level = element->level - i / m;
|
||||||
@@ -370,7 +366,6 @@ LoadNeighborsFromPage(HnswElement element, Relation index, Page page)
|
|||||||
neighbors = &element->neighbors[level];
|
neighbors = &element->neighbors[level];
|
||||||
hc = &neighbors->items[neighbors->length++];
|
hc = &neighbors->items[neighbors->length++];
|
||||||
hc->element = e;
|
hc->element = e;
|
||||||
hc->distance = neighbor->distance;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -850,31 +845,35 @@ UpdateConnections(HnswElement element, List *neighbors, int m, int lc, List **up
|
|||||||
HnswCandidate *pruned = NULL;
|
HnswCandidate *pruned = NULL;
|
||||||
List *c = NIL;
|
List *c = NIL;
|
||||||
|
|
||||||
|
/* Load elements on insert */
|
||||||
|
if (index != NULL)
|
||||||
|
{
|
||||||
|
Datum q = PointerGetDatum(hc->element->vec);
|
||||||
|
|
||||||
|
for (int i = 0; i < currentNeighbors->length; i++)
|
||||||
|
{
|
||||||
|
HnswCandidate *hc3 = ¤tNeighbors->items[i];
|
||||||
|
|
||||||
|
if (hc3->element->vec == NULL)
|
||||||
|
HnswLoadElement(hc3->element, &hc3->distance, &q, index, procinfo, collation, true);
|
||||||
|
else
|
||||||
|
hc3->distance = GetCandidateDistance(hc3, q, procinfo, collation);
|
||||||
|
|
||||||
|
/* Prune deleted element */
|
||||||
|
if (hc3->element->deleted)
|
||||||
|
{
|
||||||
|
pruned = ¤tNeighbors->items[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Add and sort candidates */
|
/* Add and sort candidates */
|
||||||
for (int i = 0; i < currentNeighbors->length; i++)
|
for (int i = 0; i < currentNeighbors->length; i++)
|
||||||
c = lappend(c, ¤tNeighbors->items[i]);
|
c = lappend(c, ¤tNeighbors->items[i]);
|
||||||
c = lappend(c, &hc2);
|
c = lappend(c, &hc2);
|
||||||
list_sort(c, CompareCandidateDistances);
|
list_sort(c, CompareCandidateDistances);
|
||||||
|
|
||||||
/* Load elements on insert */
|
|
||||||
if (index != NULL)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < currentNeighbors->length; i++)
|
|
||||||
{
|
|
||||||
if (currentNeighbors->items[i].element->vec == NULL)
|
|
||||||
{
|
|
||||||
HnswLoadElement(currentNeighbors->items[i].element, NULL, NULL, index, procinfo, collation, true);
|
|
||||||
|
|
||||||
/* Prune deleted element */
|
|
||||||
if (currentNeighbors->items[i].element->deleted)
|
|
||||||
{
|
|
||||||
pruned = ¤tNeighbors->items[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pruned == NULL)
|
if (pruned == NULL)
|
||||||
{
|
{
|
||||||
SelectNeighbors(c, m, lc, procinfo, collation, &pruned);
|
SelectNeighbors(c, m, lc, procinfo, collation, &pruned);
|
||||||
|
|||||||
@@ -156,13 +156,13 @@ NeedsUpdated(HnswVacuumState * vacuumstate, HnswElement element)
|
|||||||
/* Check neighbors */
|
/* Check neighbors */
|
||||||
for (int i = 0; i < ntup->count; i++)
|
for (int i = 0; i < ntup->count; i++)
|
||||||
{
|
{
|
||||||
HnswNeighborTupleItem *neighbor = &ntup->neighbors[i];
|
ItemPointer indextid = &ntup->indextids[i];
|
||||||
|
|
||||||
if (!ItemPointerIsValid(&neighbor->indextid))
|
if (!ItemPointerIsValid(indextid))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Check if in deleted list */
|
/* Check if in deleted list */
|
||||||
if (DeletedContains(vacuumstate->deleted, &neighbor->indextid))
|
if (DeletedContains(vacuumstate->deleted, indextid))
|
||||||
{
|
{
|
||||||
needsUpdated = true;
|
needsUpdated = true;
|
||||||
break;
|
break;
|
||||||
@@ -453,10 +453,7 @@ MarkDeleted(HnswVacuumState * vacuumstate)
|
|||||||
|
|
||||||
/* Overwrite neighbors */
|
/* Overwrite neighbors */
|
||||||
for (int i = 0; i < ntup->count; i++)
|
for (int i = 0; i < ntup->count; i++)
|
||||||
{
|
ItemPointerSetInvalid(&ntup->indextids[i]);
|
||||||
ItemPointerSetInvalid(&ntup->neighbors[i].indextid);
|
|
||||||
ntup->neighbors[i].distance = NAN;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Overwrite element tuple */
|
/* Overwrite element tuple */
|
||||||
if (!PageIndexTupleOverwrite(page, offno, (Item) etup, etupSize))
|
if (!PageIndexTupleOverwrite(page, offno, (Item) etup, etupSize))
|
||||||
|
|||||||
Reference in New Issue
Block a user