From: Alvaro Herrera <alvherre@alvh.no-ip.org>
To: Tomas Vondra <tomas.vondra@enterprisedb.com>
Cc: Alexander Lakhin <exclusion@gmail.com>
Cc: Soumyadeep Chakraborty <soumyadeep2007@gmail.com>
Cc: Matthias van de Meent <boekewurm+postgres@gmail.com>
Cc: pgsql-hackers <pgsql-hackers@postgresql.org>
Cc: Ashwin Agrawal <ashwinstar@gmail.com>
Subject: Re: brininsert optimization opportunity
Date: Tue, 9 Jan 2024 11:43:56 +0100
Message-ID: <202401091043.e3nrqiad6gb7@alvherre.pgsql> (raw)
In-Reply-To: <202401081551.3olwx6pyw2mn@alvherre.pgsql>
On 2024-Jan-08, Alvaro Herrera wrote:
> So I think we should do 0001 and perhaps some further tweaks to the
> original brininsert optimization commit: [...]
So I propose the attached patch, which should fix the reported bug and
the things I mentioned above, and also the typos Alexander mentioned
elsewhere in the thread.
> Lastly, I kinda disagree with the notion that only some of the callers
> of aminsert should call aminsertcleanup, even though btree doesn't have
> an aminsertcleanup and thus it can't affect TOAST or catalogs. [...]
I didn't do anything about this.
--
Álvaro Herrera Breisgau, Deutschland — https://www.EnterpriseDB.com/Attachments:v2-0001-call-cleanup-in-validate_index.patch (text/x-diff, 7.2K) download
From 5eff6872a446c7a3e86607b5d73a18e1a95b7da7 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tomas.vondra@postgresql.org>
Date: Tue, 12 Dec 2023 12:01:07 +0100
Subject: [PATCH v2] call cleanup in validate_index
---
doc/src/sgml/indexam.sgml | 14 +++++++-------
src/backend/access/brin/brin.c | 19 +++++++++++--------
src/backend/access/index/indexam.c | 5 ++---
src/backend/catalog/index.c | 2 ++
src/include/access/amapi.h | 2 +-
src/include/access/brin_internal.h | 2 +-
6 files changed, 24 insertions(+), 20 deletions(-)
diff --git a/doc/src/sgml/indexam.sgml b/doc/src/sgml/indexam.sgmlindex cc4135e394..4817acd31f 100644--- a/doc/src/sgml/indexam.sgml+++ b/doc/src/sgml/indexam.sgml@@ -367,21 +367,21 @@ aminsert (Relation indexRelation,
within an SQL statement, it can allocate space
in <literal>indexInfo->ii_Context</literal> and store a pointer to the
data in <literal>indexInfo->ii_AmCache</literal> (which will be NULL
- initially). After the index insertions complete, the memory will be freed- automatically. If additional cleanup is required (e.g. if the cache contains- buffers and tuple descriptors), the AM may define an optional function- <literal>indexinsertcleanup</literal>, called before the memory is released.+ initially). If resources other than memory have to be released+ after index insertions, <function>aminsertcleanup</function> may+ be provided, which will be called before the memory is released.
</para>
<para>
<programlisting>
void
-aminsertcleanup (IndexInfo *indexInfo);+aminsertcleanup (Relation indexRelation,+ IndexInfo *indexInfo);
</programlisting>
Clean up state that was maintained across successive inserts in
<literal>indexInfo->ii_AmCache</literal>. This is useful if the data
- requires additional cleanup steps, and simply releasing the memory is not- sufficient.+ requires additional cleanup steps (e.g., releasing pinned+ buffers), and simply releasing the memory is not sufficient.
</para>
<para>
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.cindex 1087a9011e..6ac12b9ba8 100644--- a/src/backend/access/brin/brin.c+++ b/src/backend/access/brin/brin.c@@ -222,7 +222,7 @@ static bool add_values_to_range(Relation idxRel, BrinDesc *bdesc,
BrinMemTuple *dtup, const Datum *values, const bool *nulls);
static bool check_null_keys(BrinValues *bval, ScanKey *nullkeys, int nnullkeys);
static void brin_fill_empty_ranges(BrinBuildState *state,
- BlockNumber prevRange, BlockNumber maxRange);+ BlockNumber prevRange, BlockNumber nextRange);
/* parallel index builds */
static void _brin_begin_parallel(BrinBuildState *buildstate, Relation heap, Relation index,
@@ -498,11 +498,14 @@ brininsert(Relation idxRel, Datum *values, bool *nulls,
* Callback to clean up the BrinInsertState once all tuple inserts are done.
*/
void
-brininsertcleanup(IndexInfo *indexInfo)+brininsertcleanup(Relation idx, IndexInfo *indexInfo)
{
- BrinInsertState *bistate = (BrinInsertState *) indexInfo->ii_AmCache;+ BrinInsertState *bistate;- Assert(bistate);+ if (indexInfo->ii_AmCache == NULL)+ return;++ bistate = (BrinInsertState *) indexInfo->ii_AmCache;
/*
* Clean up the revmap. Note that the brinDesc has already been cleaned up
@@ -1149,8 +1152,8 @@ brinbuild(Relation heap, Relation index, IndexInfo *indexInfo)
*
* XXX plan_create_index_workers makes the number of workers dependent on
* maintenance_work_mem, requiring 32MB for each worker. That makes sense
- * for btree, but not for BRIN, which can do away with much less memory.- * So maybe make that somehow less strict, optionally?+ * for btree, but not for BRIN, which can do with much less memory. So+ * maybe make that somehow less strict, optionally?
*/
if (indexInfo->ii_ParallelWorkers > 0)
_brin_begin_parallel(state, heap, index, indexInfo->ii_Concurrent,
@@ -2543,7 +2546,7 @@ _brin_end_parallel(BrinLeader *brinleader, BrinBuildState *state)
/*
* Initialize BrinMemTuple we'll use to union summaries from workers (in
- * case they happened to produce parts of the same paga range).+ * case they happened to produce parts of the same page range).
*/
memtuple = brin_new_memtuple(state->bs_bdesc);
@@ -2867,7 +2870,7 @@ _brin_parallel_build_main(dsm_segment *seg, shm_toc *toc)
* specified block number. The empty tuple is initialized only once, when it's
* needed for the first time, stored in the memory context bs_context to ensure
* proper life span, and reused on following calls. All empty tuples are
- * exactly the same except for the bs_blkno field, which is set to the value+ * exactly the same except for the bt_blkno field, which is set to the value
* in blkno parameter.
*/
static void
diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.cindex 63dff101e2..ff84bf0fa0 100644--- a/src/backend/access/index/indexam.c+++ b/src/backend/access/index/indexam.c@@ -205,10 +205,9 @@ index_insert_cleanup(Relation indexRelation,
IndexInfo *indexInfo)
{
RELATION_CHECKS;
- Assert(indexInfo);- if (indexRelation->rd_indam->aminsertcleanup && indexInfo->ii_AmCache)- indexRelation->rd_indam->aminsertcleanup(indexInfo);+ if (indexRelation->rd_indam->aminsertcleanup)+ indexRelation->rd_indam->aminsertcleanup(indexRelation, indexInfo);
}
/*
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.cindex 88f7994b5a..40ac683b35 100644--- a/src/backend/catalog/index.c+++ b/src/backend/catalog/index.c@@ -3414,6 +3414,8 @@ validate_index(Oid heapId, Oid indexId, Snapshot snapshot)
/* Done with tuplesort object */
tuplesort_end(state.tuplesort);
+ index_insert_cleanup(indexRelation, indexInfo);+
elog(DEBUG2,
"validate_index found %.0f heap tuples, %.0f index tuples; inserted %.0f missing tuples",
state.htups, state.itups, state.tups_inserted);
diff --git a/src/include/access/amapi.h b/src/include/access/amapi.hindex 2c6c307efc..683ad13f07 100644--- a/src/include/access/amapi.h+++ b/src/include/access/amapi.h@@ -114,7 +114,7 @@ typedef bool (*aminsert_function) (Relation indexRelation,
struct IndexInfo *indexInfo);
/* cleanup after insert */
-typedef void (*aminsertcleanup_function) (struct IndexInfo *indexInfo);+typedef void (*aminsertcleanup_function) (Relation indexRelation, struct IndexInfo *indexInfo);
/* bulk delete */
typedef IndexBulkDeleteResult *(*ambulkdelete_function) (IndexVacuumInfo *info,
diff --git a/src/include/access/brin_internal.h b/src/include/access/brin_internal.hindex 1c7eabe604..a5a9772621 100644--- a/src/include/access/brin_internal.h+++ b/src/include/access/brin_internal.h@@ -96,7 +96,7 @@ extern bool brininsert(Relation idxRel, Datum *values, bool *nulls,
IndexUniqueCheck checkUnique,
bool indexUnchanged,
struct IndexInfo *indexInfo);
-extern void brininsertcleanup(struct IndexInfo *indexInfo);+extern void brininsertcleanup(Relation index, struct IndexInfo *indexInfo);
extern IndexScanDesc brinbeginscan(Relation r, int nkeys, int norderbys);
extern int64 bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm);
extern void brinrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys,
--
2.39.2
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-hackers@postgresql.org
Cc: alvherre@alvh.no-ip.org, tomas.vondra@enterprisedb.com, exclusion@gmail.com, soumyadeep2007@gmail.com, boekewurm+postgres@gmail.com, ashwinstar@gmail.com
Subject: Re: brininsert optimization opportunity
In-Reply-To: <202401091043.e3nrqiad6gb7@alvherre.pgsql>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox