Improved inserts for HNSW

This commit is contained in:
Andrew Kane
2023-08-11 09:23:56 -07:00
parent c64288377b
commit 12d15a9c41

View File

@@ -118,6 +118,7 @@ WriteNewElementPages(Relation index, HnswElement e, int m, BlockNumber insertPag
Size etupSize; Size etupSize;
Size ntupSize; Size ntupSize;
Size combinedSize; Size combinedSize;
Size maxSize;
HnswElementTuple etup; HnswElementTuple etup;
BlockNumber originalInsertPage = insertPage; BlockNumber originalInsertPage = insertPage;
int dimensions = e->vec->dim; int dimensions = e->vec->dim;
@@ -132,6 +133,7 @@ WriteNewElementPages(Relation index, HnswElement e, int m, BlockNumber insertPag
etupSize = HNSW_ELEMENT_TUPLE_SIZE(dimensions); etupSize = HNSW_ELEMENT_TUPLE_SIZE(dimensions);
ntupSize = HNSW_NEIGHBOR_TUPLE_SIZE(e->level, m); ntupSize = HNSW_NEIGHBOR_TUPLE_SIZE(e->level, m);
combinedSize = etupSize + ntupSize + sizeof(ItemIdData); combinedSize = etupSize + ntupSize + sizeof(ItemIdData);
maxSize = BLCKSZ - MAXALIGN(SizeOfPageHeaderData) - MAXALIGN(sizeof(HnswPageOpaqueData));
/* Prepare element tuple */ /* Prepare element tuple */
etup = palloc0(etupSize); etup = palloc0(etupSize);
@@ -141,7 +143,7 @@ WriteNewElementPages(Relation index, HnswElement e, int m, BlockNumber insertPag
ntup = palloc0(ntupSize); ntup = palloc0(ntupSize);
HnswSetNeighborTuple(ntup, e, m); HnswSetNeighborTuple(ntup, e, m);
/* Find a page to insert the item */ /* Find a page (or two if needed) to insert the tuples */
for (;;) for (;;)
{ {
buf = ReadBuffer(index, insertPage); buf = ReadBuffer(index, insertPage);
@@ -150,7 +152,8 @@ WriteNewElementPages(Relation index, HnswElement e, int m, BlockNumber insertPag
state = GenericXLogStart(index); state = GenericXLogStart(index);
page = GenericXLogRegisterBuffer(state, buf, 0); page = GenericXLogRegisterBuffer(state, buf, 0);
/* Space for both */ /* First, try the fastest path */
/* Space for both tuples on the current page */
if (PageGetFreeSpace(page) >= combinedSize) if (PageGetFreeSpace(page) >= combinedSize)
{ {
nbuf = buf; nbuf = buf;
@@ -158,14 +161,7 @@ WriteNewElementPages(Relation index, HnswElement e, int m, BlockNumber insertPag
break; break;
} }
/* Space for element but not neighbors and last page */ /* Next, try space from a deleted element */
if (PageGetFreeSpace(page) >= etupSize && !BlockNumberIsValid(HnswPageGetOpaque(page)->nextblkno))
{
HnswInsertAppendPage(index, &nbuf, &npage, state, page);
break;
}
/* Space from deleted item */
if (HnswFreeOffset(index, buf, page, e, ntupSize, &nbuf, &npage, &freeOffno, &freeNeighborOffno, &firstFreePage)) if (HnswFreeOffset(index, buf, page, e, ntupSize, &nbuf, &npage, &freeOffno, &freeNeighborOffno, &firstFreePage))
{ {
if (nbuf != buf) if (nbuf != buf)
@@ -174,6 +170,14 @@ WriteNewElementPages(Relation index, HnswElement e, int m, BlockNumber insertPag
break; break;
} }
/* Finally, try space for element only if last page */
/* Skip if element and neighbor can fit on the same page */
if (combinedSize > maxSize && PageGetFreeSpace(page) >= etupSize && !BlockNumberIsValid(HnswPageGetOpaque(page)->nextblkno))
{
HnswInsertAppendPage(index, &nbuf, &npage, state, page);
break;
}
insertPage = HnswPageGetOpaque(page)->nextblkno; insertPage = HnswPageGetOpaque(page)->nextblkno;
if (BlockNumberIsValid(insertPage)) if (BlockNumberIsValid(insertPage))