Improved pattern for duplicates

This commit is contained in:
Andrew Kane
2024-01-12 14:30:13 -08:00
parent 423cc2b06c
commit cacd389f6d

View File

@@ -5,6 +5,7 @@
#include "hnsw.h" #include "hnsw.h"
#include "storage/bufmgr.h" #include "storage/bufmgr.h"
#include "storage/lmgr.h" #include "storage/lmgr.h"
#include "utils/datum.h"
#include "utils/memutils.h" #include "utils/memutils.h"
/* /*
@@ -446,7 +447,7 @@ HnswUpdateNeighborPages(Relation index, FmgrInfo *procinfo, Oid collation, HnswE
* Add a heap TID to an existing element * Add a heap TID to an existing element
*/ */
static bool static bool
HnswAddDuplicate(Relation index, HnswElement element, HnswElement dup, bool building) HnswAddDuplicateToPage(Relation index, HnswElement element, HnswElement dup, bool building)
{ {
Buffer buf; Buffer buf;
Page page; Page page;
@@ -506,20 +507,41 @@ HnswAddDuplicate(Relation index, HnswElement element, HnswElement dup, bool buil
return true; return true;
} }
/*
* Add duplicate if found
*/
static bool
HnswAddDuplicateIfFound(Relation index, HnswElement element, bool building)
{
HnswNeighborArray *neighbors = &element->neighbors[0];
for (int i = 0; i < neighbors->length; i++)
{
HnswCandidate *neighbor = &neighbors->items[i];
/* Exit early if not duplicate since ordered by distance */
if (!datumIsEqual(element->value, neighbor->element->value, false, -1))
return false;
/* If adding fails, continue to next duplicate element */
if (HnswAddDuplicateToPage(index, element, neighbor->element, building))
return true;
}
return false;
}
/* /*
* Write changes to disk * Write changes to disk
*/ */
static void static void
WriteElement(Relation index, FmgrInfo *procinfo, Oid collation, HnswElement element, int m, int efConstruction, HnswElement dup, HnswElement entryPoint, bool building) WriteElement(Relation index, FmgrInfo *procinfo, Oid collation, HnswElement element, int m, int efConstruction, HnswElement entryPoint, bool building)
{ {
BlockNumber newInsertPage = InvalidBlockNumber; BlockNumber newInsertPage = InvalidBlockNumber;
/* Try to add to existing page */ /* Try to add to existing page */
if (dup != NULL) if (HnswAddDuplicateIfFound(index, element, building))
{ return;
if (HnswAddDuplicate(index, element, dup, building))
return;
}
/* Write element and neighbor tuples */ /* Write element and neighbor tuples */
WriteNewElementPages(index, element, m, GetInsertPage(index), &newInsertPage, building); WriteNewElementPages(index, element, m, GetInsertPage(index), &newInsertPage, building);
@@ -550,7 +572,6 @@ HnswInsertTuple(Relation index, Datum *values, bool *isnull, ItemPointer heap_ti
int efConstruction = HnswGetEfConstruction(index); int efConstruction = HnswGetEfConstruction(index);
FmgrInfo *procinfo = index_getprocinfo(index, 1, HNSW_DISTANCE_PROC); FmgrInfo *procinfo = index_getprocinfo(index, 1, HNSW_DISTANCE_PROC);
Oid collation = index->rd_indcollation[0]; Oid collation = index->rd_indcollation[0];
HnswElement dup;
LOCKMODE lockmode = ShareLock; LOCKMODE lockmode = ShareLock;
/* Detoast once for all calls */ /* Detoast once for all calls */
@@ -595,11 +616,8 @@ HnswInsertTuple(Relation index, Datum *values, bool *isnull, ItemPointer heap_ti
/* Insert element in graph */ /* Insert element in graph */
HnswInsertElement(element, entryPoint, index, procinfo, collation, m, efConstruction, false); HnswInsertElement(element, entryPoint, index, procinfo, collation, m, efConstruction, false);
/* Look for duplicate */
dup = HnswFindDuplicate(element);
/* Write to disk */ /* Write to disk */
WriteElement(index, procinfo, collation, element, m, efConstruction, dup, entryPoint, building); WriteElement(index, procinfo, collation, element, m, efConstruction, entryPoint, building);
/* Release lock */ /* Release lock */
UnlockPage(index, HNSW_UPDATE_LOCK, lockmode); UnlockPage(index, HNSW_UPDATE_LOCK, lockmode);