From b7c2068b76b9380cf397baf8fe933121985b8646 Mon Sep 17 00:00:00 2001 From: Andrew Kane Date: Wed, 17 Jun 2026 11:27:24 -0700 Subject: [PATCH] Switched to TidStore for HNSW vacuuming for Postgres 17+ --- src/hnsw.c | 10 +++++++++- src/hnsw.h | 8 +++++++- src/hnswvacuum.c | 32 +++++++++++++++++++++++++++++++- 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/hnsw.c b/src/hnsw.c index a3f5822..4b1017b 100644 --- a/src/hnsw.c +++ b/src/hnsw.c @@ -290,7 +290,11 @@ hnswhandler(PG_FUNCTION_ARGS) .amcanparallel = false, .amcanbuildparallel = true, .amcaninclude = false, +#if PG_VERSION_NUM >= 170000 + .amusemaintenanceworkmem = true, +#else .amusemaintenanceworkmem = false, +#endif .amsummarizing = false, .amparallelvacuumoptions = VACUUM_OPTION_PARALLEL_BULKDEL, .amkeytype = InvalidOid, @@ -351,7 +355,11 @@ hnswhandler(PG_FUNCTION_ARGS) amroutine->amcanbuildparallel = true; #endif amroutine->amcaninclude = false; - amroutine->amusemaintenanceworkmem = false; /* not used during VACUUM */ +#if PG_VERSION_NUM >= 170000 + amroutine->amusemaintenanceworkmem = true; +#else + amroutine->amusemaintenanceworkmem = false; +#endif #if PG_VERSION_NUM >= 160000 amroutine->amsummarizing = false; #endif diff --git a/src/hnsw.h b/src/hnsw.h index 08293be..484db82 100644 --- a/src/hnsw.h +++ b/src/hnsw.h @@ -26,6 +26,12 @@ typedef Pointer Item; #endif +#if PG_VERSION_NUM >= 170000 +#define HnswTidStore TidStore +#else +#define HnswTidStore tidhash_hash +#endif + #define HNSW_MAX_DIM 2000 #define HNSW_MAX_NNZ 1000 @@ -427,7 +433,7 @@ typedef struct HnswVacuumState HnswSupport support; /* Variables */ - struct tidhash_hash *deleted; + struct HnswTidStore *deleted; BufferAccessStrategy bas; HnswNeighborTuple ntup; HnswElementData highestPoint; diff --git a/src/hnswvacuum.c b/src/hnswvacuum.c index cdc3b94..91f37ab 100644 --- a/src/hnswvacuum.c +++ b/src/hnswvacuum.c @@ -10,6 +10,12 @@ #include "utils/memutils.h" #include "utils/rel.h" +#if PG_VERSION_NUM >= 170000 +#include "access/tidstore.h" +#include "miscadmin.h" +#include "postmaster/autovacuum.h" +#endif + #if PG_VERSION_NUM >= 160000 #include "varatt.h" #endif @@ -22,9 +28,13 @@ * Check if deleted list contains an index TID */ static bool -DeletedContains(tidhash_hash * deleted, ItemPointer indextid) +DeletedContains(HnswTidStore * deleted, ItemPointer indextid) { +#if PG_VERSION_NUM >= 170000 + return TidStoreIsMember(deleted, indextid); +#else return tidhash_lookup(deleted, *indextid) != NULL; +#endif } /* @@ -60,6 +70,10 @@ RemoveHeapTids(HnswVacuumState * vacuumstate) OffsetNumber offno; OffsetNumber maxoffno; bool updated = false; +#if PG_VERSION_NUM >= 170000 + OffsetNumber deletedoffs[MaxOffsetNumber]; + int ndeletedoffs = 0; +#endif vacuum_delay_point(); @@ -113,6 +127,9 @@ RemoveHeapTids(HnswVacuumState * vacuumstate) if (!ItemPointerIsValid(&etup->heaptids[0])) { +#if PG_VERSION_NUM >= 170000 + deletedoffs[ndeletedoffs++] = offno; +#else ItemPointerData ip; bool found; @@ -121,6 +138,7 @@ RemoveHeapTids(HnswVacuumState * vacuumstate) tidhash_insert(vacuumstate->deleted, ip, &found); Assert(!found); +#endif } else if (etup->level > highestLevel) { @@ -149,6 +167,10 @@ RemoveHeapTids(HnswVacuumState * vacuumstate) } } +#if PG_VERSION_NUM >= 170000 + TidStoreSetBlockOffsets(vacuumstate->deleted, blkno, deletedoffs, ndeletedoffs); +#endif + blkno = HnswPageGetOpaque(page)->nextblkno; if (updated) @@ -739,7 +761,11 @@ InitVacuumState(HnswVacuumState * vacuumstate, IndexVacuumInfo *info, IndexBulkD HnswGetMetaPageInfo(index, &vacuumstate->m, NULL); /* Create hash table */ +#if PG_VERSION_NUM >= 170000 + vacuumstate->deleted = TidStoreCreateLocal((AmAutoVacuumWorkerProcess() && autovacuum_work_mem != -1) ? autovacuum_work_mem : maintenance_work_mem, true); +#else vacuumstate->deleted = tidhash_create(CurrentMemoryContext, 256, NULL); +#endif } /* @@ -748,7 +774,11 @@ InitVacuumState(HnswVacuumState * vacuumstate, IndexVacuumInfo *info, IndexBulkD static void FreeVacuumState(HnswVacuumState * vacuumstate) { +#if PG_VERSION_NUM >= 170000 + TidStoreDestroy(vacuumstate->deleted); +#else tidhash_destroy(vacuumstate->deleted); +#endif FreeAccessStrategy(vacuumstate->bas); pfree(vacuumstate->ntup); MemoryContextDelete(vacuumstate->tmpCtx);