diff --git a/src/hnsw.h b/src/hnsw.h index bc79c8a..0a8e633 100644 --- a/src/hnsw.h +++ b/src/hnsw.h @@ -271,7 +271,7 @@ void HnswSetNeighborTuple(HnswNeighborTuple ntup, HnswElement e, int m); void HnswAddHeapTid(HnswElement element, ItemPointer heaptid); void HnswInitNeighbors(HnswElement element, int m); bool HnswInsertTuple(Relation index, Datum *values, bool *isnull, ItemPointer heap_tid, Relation heapRel); -void UpdateNeighborPages(Relation index, FmgrInfo *procinfo, Oid collation, HnswElement e, int m); +void UpdateNeighborPages(Relation index, FmgrInfo *procinfo, Oid collation, HnswElement e, int m, bool checkExisting); void HnswLoadElement(HnswElement element, float *distance, Datum *q, Relation index, FmgrInfo *procinfo, Oid collation, bool loadVec); void HnswSetElementTuple(HnswElementTuple etup, HnswElement element); void HnswUpdateConnection(HnswElement element, HnswCandidate * hc, int m, int lc, int *updateIdx, Relation index, FmgrInfo *procinfo, Oid collation); diff --git a/src/hnswinsert.c b/src/hnswinsert.c index 0e52f10..3ac793e 100644 --- a/src/hnswinsert.c +++ b/src/hnswinsert.c @@ -283,11 +283,28 @@ WriteNewElementPages(Relation index, HnswElement e, int m, BlockNumber insertPag *updatedInsertPage = newInsertPage; } +/* + * Check if connection already exists + */ +static bool +ConnectionExists(HnswElement e, HnswNeighborTuple ntup, int startIdx, int lm) +{ + for (int i = 0; i < lm; i++) + { + ItemPointer indextid = &ntup->indextids[startIdx + i]; + + if (ItemPointerGetBlockNumber(indextid) == e->blkno && ItemPointerGetOffsetNumber(indextid) == e->offno) + return true; + } + + return false; +} + /* * Update neighbors */ void -UpdateNeighborPages(Relation index, FmgrInfo *procinfo, Oid collation, HnswElement e, int m) +UpdateNeighborPages(Relation index, FmgrInfo *procinfo, Oid collation, HnswElement e, int m, bool checkExisting) { for (int lc = e->level; lc >= 0; lc--) { @@ -339,7 +356,10 @@ UpdateNeighborPages(Relation index, FmgrInfo *procinfo, Oid collation, HnswEleme /* Calculate index for update */ startIdx = (hc->element->level - lc) * m; - if (idx == -2) + /* Check for existing connection */ + if (checkExisting && ConnectionExists(e, ntup, startIdx, lm)) + idx = -1; + else if (idx == -2) { /* Find free offset if still exists */ /* TODO Retry updating connections if not */ @@ -496,7 +516,7 @@ WriteElement(Relation index, FmgrInfo *procinfo, Oid collation, HnswElement elem HnswUpdateMetaPage(index, 0, NULL, newInsertPage, MAIN_FORKNUM); /* Update neighbors */ - UpdateNeighborPages(index, procinfo, collation, element, m); + UpdateNeighborPages(index, procinfo, collation, element, m, false); /* Update metapage if needed */ if (element->level > entryPoint->level) diff --git a/src/hnswvacuum.c b/src/hnswvacuum.c index eb7c869..6f137e2 100644 --- a/src/hnswvacuum.c +++ b/src/hnswvacuum.c @@ -255,7 +255,7 @@ RepairGraphElement(HnswVacuumState * vacuumstate, HnswElement element) UnlockReleaseBuffer(buf); /* Update neighbors */ - UpdateNeighborPages(index, procinfo, collation, element, m); + UpdateNeighborPages(index, procinfo, collation, element, m, true); } /*