From 54ba134f4afe9c4bac19e7d8fde31b9768dc23cd Mon Sep 17 00:00:00 2001 From: Soumyadeep Chakraborty Date: Tue, 4 Jul 2023 11:50:35 -0700 Subject: [PATCH v2 1/1] Reuse revmap and brin desc in brininsert brininsert() used to have code that performed per-tuple initialization of the revmap. That had some overhead. --- src/backend/access/brin/brin.c | 89 +++++++++++++++++++++++++++++----- 1 file changed, 78 insertions(+), 11 deletions(-) diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c index 3c6a956eaa3..32b588af4da 100644 --- a/src/backend/access/brin/brin.c +++ b/src/backend/access/brin/brin.c @@ -58,6 +58,17 @@ typedef struct BrinBuildState BrinMemTuple *bs_dtuple; } BrinBuildState; +/* + * We use a BrinInsertState to capture running state spanning multiple + * brininsert invocations, within the same command. + */ +typedef struct BrinInsertState +{ + BrinRevmap *bs_rmAccess; + BrinDesc *bs_desc; + BlockNumber bs_pages_per_range; +} BrinInsertState; + /* * Struct used as "opaque" during index scans */ @@ -72,6 +83,8 @@ typedef struct BrinOpaque static BrinBuildState *initialize_brin_buildstate(Relation idxRel, BrinRevmap *revmap, BlockNumber pagesPerRange); +static void brininsertCleanupCallback(void *arg); +static BrinInsertState *initialize_brin_insertstate(Relation idxRel); static void terminate_brin_buildstate(BrinBuildState *state); static void brinsummarize(Relation index, Relation heapRel, BlockNumber pageRange, bool include_partial, double *numSummarized, double *numExisting); @@ -140,6 +153,60 @@ brinhandler(PG_FUNCTION_ARGS) PG_RETURN_POINTER(amroutine); } +/* + * Callback to clean up the BrinInsertState once all tuple inserts are done. + */ +static void +brininsertCleanupCallback(void *arg) +{ + BrinInsertState *bistate = (BrinInsertState *) arg; + + /* + * Clean up the revmap. Note that the brinDesc has already been cleaned up + * as part of its own memory context. + */ + brinRevmapTerminate(bistate->bs_rmAccess); + bistate->bs_rmAccess = NULL; + bistate->bs_desc = NULL; +} + +/* + * Initialize a BrinInsertState to maintain state to be used across multiple + * tuple inserts, within the same command. + */ +static BrinInsertState * +initialize_brin_insertstate(Relation idxRel) +{ + BrinInsertState *bistate; + MemoryContextCallback *cb; + MemoryContext cxt; + MemoryContext oldcxt; + + /* + * Create private context for holding the BrinInsertState to ensure that we + * clean up the revmap safely in the callback. + */ + cxt = AllocSetContextCreate(CurrentMemoryContext, + "brin insert cxt", + ALLOCSET_SMALL_SIZES); + oldcxt = MemoryContextSwitchTo(cxt); + + bistate = palloc0(sizeof(BrinInsertState)); + bistate->bs_desc = brin_build_desc(idxRel); + cb = palloc(sizeof(MemoryContextCallback)); + cb->arg = bistate; + cb->func = brininsertCleanupCallback; + MemoryContextRegisterResetCallback(CurrentMemoryContext, cb); + + MemoryContextSwitchTo(oldcxt); + + bistate->bs_rmAccess = brinRevmapInitialize(idxRel, + &bistate->bs_pages_per_range, + NULL); + + return bistate; +} + /* * A tuple in the heap is being inserted. To keep a brin index up to date, * we need to obtain the relevant index tuple and compare its stored values @@ -162,14 +229,23 @@ brininsert(Relation idxRel, Datum *values, bool *nulls, BlockNumber pagesPerRange; BlockNumber origHeapBlk; BlockNumber heapBlk; - BrinDesc *bdesc = (BrinDesc *) indexInfo->ii_AmCache; + BrinInsertState *bistate = (BrinInsertState *) indexInfo->ii_AmCache; BrinRevmap *revmap; + BrinDesc *bdesc; Buffer buf = InvalidBuffer; MemoryContext tupcxt = NULL; MemoryContext oldcxt = CurrentMemoryContext; bool autosummarize = BrinGetAutoSummarize(idxRel); - revmap = brinRevmapInitialize(idxRel, &pagesPerRange, NULL); + if (!bistate) + { + /* First time through in this statement? */ + bistate = initialize_brin_insertstate(idxRel); + indexInfo->ii_AmCache = (void *) bistate; + } + revmap = bistate->bs_rmAccess; + bdesc = bistate->bs_desc; + pagesPerRange = bistate->bs_pages_per_range; /* * origHeapBlk is the block number where the insertion occurred. heapBlk @@ -228,14 +304,6 @@ brininsert(Relation idxRel, Datum *values, bool *nulls, if (!brtup) break; - /* First time through in this statement? */ - if (bdesc == NULL) - { - MemoryContextSwitchTo(indexInfo->ii_Context); - bdesc = brin_build_desc(idxRel); - indexInfo->ii_AmCache = (void *) bdesc; - MemoryContextSwitchTo(oldcxt); - } /* First time through in this brininsert call? */ if (tupcxt == NULL) { @@ -306,7 +374,6 @@ brininsert(Relation idxRel, Datum *values, bool *nulls, break; } - brinRevmapTerminate(revmap); if (BufferIsValid(buf)) ReleaseBuffer(buf); MemoryContextSwitchTo(oldcxt); -- 2.34.1