v1-0002-Convert-IndexBulkDeleteCallback-to-process-TIDs-i.patch
application/x-patch
Filename: v1-0002-Convert-IndexBulkDeleteCallback-to-process-TIDs-i.patch
Type: application/x-patch
Part: 2
Message:
Batch TIDs lookup in ambulkdelete
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v1-0002
Subject: Convert IndexBulkDeleteCallback to process TIDs in batch.
| File | + | − |
|---|---|---|
| contrib/bloom/blvacuum.c | 3 | 1 |
| src/backend/access/gin/ginvacuum.c | 2 | 1 |
| src/backend/access/gist/gistvacuum.c | 2 | 1 |
| src/backend/access/hash/hash.c | 2 | 1 |
| src/backend/access/nbtree/nbtree.c | 2 | 2 |
| src/backend/access/spgist/spgvacuum.c | 8 | 5 |
| src/backend/catalog/index.c | 14 | 7 |
| src/backend/commands/vacuum.c | 4 | 4 |
| src/include/access/genam.h | 2 | 1 |
From e693adff50f09fe791c87a444950b193b642aabb Mon Sep 17 00:00:00 2001
From: Masahiko Sawada <sawada.mshk@gmail.com>
Date: Mon, 21 Apr 2025 22:41:33 -0700
Subject: [PATCH v1 2/3] Convert IndexBulkDeleteCallback to process TIDs in
batch.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch-through:
---
contrib/bloom/blvacuum.c | 4 +++-
src/backend/access/gin/ginvacuum.c | 3 ++-
src/backend/access/gist/gistvacuum.c | 3 ++-
src/backend/access/hash/hash.c | 3 ++-
src/backend/access/nbtree/nbtree.c | 4 ++--
src/backend/access/spgist/spgvacuum.c | 13 ++++++++-----
src/backend/catalog/index.c | 21 ++++++++++++++-------
src/backend/commands/vacuum.c | 8 ++++----
src/include/access/genam.h | 3 ++-
9 files changed, 39 insertions(+), 23 deletions(-)
diff --git a/contrib/bloom/blvacuum.c b/contrib/bloom/blvacuum.c
index 86b15a75f6f..93089456855 100644
--- a/contrib/bloom/blvacuum.c
+++ b/contrib/bloom/blvacuum.c
@@ -83,8 +83,10 @@ blbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
OffsetNumberNext(BloomPageGetMaxOffset(page)));
while (itup < itupEnd)
{
+ bool dead;
+
/* Do we have to delete this tuple? */
- if (callback(&itup->heapPtr, callback_state))
+ if (callback(&itup->heapPtr, 1, &dead, callback_state) > 0)
{
/* Yes; adjust count of tuples that will be left on page */
BloomPageGetOpaque(page)->maxoff--;
diff --git a/src/backend/access/gin/ginvacuum.c b/src/backend/access/gin/ginvacuum.c
index fbbe3a6dd70..336f100261b 100644
--- a/src/backend/access/gin/ginvacuum.c
+++ b/src/backend/access/gin/ginvacuum.c
@@ -56,7 +56,8 @@ ginVacuumItemPointers(GinVacuumState *gvs, ItemPointerData *items,
*/
for (i = 0; i < nitem; i++)
{
- if (gvs->callback(items + i, gvs->callback_state))
+ bool deletable;
+ if (gvs->callback(items + i, 1, &deletable, gvs->callback_state) > 0)
{
gvs->result->tuples_removed += 1;
if (!tmpitems)
diff --git a/src/backend/access/gist/gistvacuum.c b/src/backend/access/gist/gistvacuum.c
index 6a359c98c60..0abefb7b664 100644
--- a/src/backend/access/gist/gistvacuum.c
+++ b/src/backend/access/gist/gistvacuum.c
@@ -383,8 +383,9 @@ restart:
{
ItemId iid = PageGetItemId(page, off);
IndexTuple idxtuple = (IndexTuple) PageGetItem(page, iid);
+ bool deletable;
- if (callback(&(idxtuple->t_tid), callback_state))
+ if (callback(&(idxtuple->t_tid), 1, &deletable, callback_state) > 0)
todelete[ntodelete++] = off;
}
}
diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c
index 53061c819fb..e0fffadf698 100644
--- a/src/backend/access/hash/hash.c
+++ b/src/backend/access/hash/hash.c
@@ -734,6 +734,7 @@ hashbucketcleanup(Relation rel, Bucket cur_bucket, Buffer bucket_buf,
IndexTuple itup;
Bucket bucket;
bool kill_tuple = false;
+ bool dead;
itup = (IndexTuple) PageGetItem(page,
PageGetItemId(page, offno));
@@ -743,7 +744,7 @@ hashbucketcleanup(Relation rel, Bucket cur_bucket, Buffer bucket_buf,
* To remove the dead tuples, we strictly want to rely on results
* of callback function. refer btvacuumpage for detailed reason.
*/
- if (callback && callback(htup, callback_state))
+ if (callback && callback(htup, 1, &dead, callback_state) > 0)
{
kill_tuple = true;
if (tuples_removed)
diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c
index accc7fe8bbe..821e16d5691 100644
--- a/src/backend/access/nbtree/nbtree.c
+++ b/src/backend/access/nbtree/nbtree.c
@@ -1486,7 +1486,7 @@ backtrack:
if (!BTreeTupleIsPosting(itup))
{
/* Regular tuple, standard table TID representation */
- if (callback(&itup->t_tid, callback_state))
+ if (callback(&itup->t_tid, 1, NULL, callback_state) > 0)
{
deletable[ndeletable++] = offnum;
nhtidsdead++;
@@ -1670,7 +1670,7 @@ btreevacuumposting(BTVacState *vstate, IndexTuple posting,
for (int i = 0; i < nitem; i++)
{
- if (!vstate->callback(items + i, vstate->callback_state))
+ if (vstate->callback(items + i, 1, NULL, vstate->callback_state) == 0)
{
/* Live table TID */
live++;
diff --git a/src/backend/access/spgist/spgvacuum.c b/src/backend/access/spgist/spgvacuum.c
index 81171f35451..a9a61fa152e 100644
--- a/src/backend/access/spgist/spgvacuum.c
+++ b/src/backend/access/spgist/spgvacuum.c
@@ -153,9 +153,11 @@ vacuumLeafPage(spgBulkDeleteState *bds, Relation index, Buffer buffer,
PageGetItemId(page, i));
if (lt->tupstate == SPGIST_LIVE)
{
+ bool dead;
+
Assert(ItemPointerIsValid(<->heapPtr));
- if (bds->callback(<->heapPtr, bds->callback_state))
+ if (bds->callback(<->heapPtr, 1, &dead, bds->callback_state) > 0)
{
bds->stats->tuples_removed += 1;
deletable[i] = true;
@@ -425,9 +427,10 @@ vacuumLeafRoot(spgBulkDeleteState *bds, Relation index, Buffer buffer)
PageGetItemId(page, i));
if (lt->tupstate == SPGIST_LIVE)
{
+ bool dead;
Assert(ItemPointerIsValid(<->heapPtr));
- if (bds->callback(<->heapPtr, bds->callback_state))
+ if (bds->callback(<->heapPtr, 1, &dead, bds->callback_state) > 0)
{
bds->stats->tuples_removed += 1;
toDelete[xlrec.nDelete] = i;
@@ -965,10 +968,10 @@ spgbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
}
/* Dummy callback to delete no tuples during spgvacuumcleanup */
-static bool
-dummy_callback(ItemPointer itemptr, void *state)
+static int
+dummy_callback(ItemPointer itemptrs, int nitem, bool *deletable, void *state)
{
- return false;
+ return 0;
}
/*
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 739a92bdcc1..fc40317728f 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -126,7 +126,8 @@ static void index_update_stats(Relation rel,
static void IndexCheckExclusion(Relation heapRelation,
Relation indexRelation,
IndexInfo *indexInfo);
-static bool validate_index_callback(ItemPointer itemptr, void *opaque);
+static int validate_index_callback(ItemPointer itemptrs, int nitem, bool *deletable,
+ void *opaque);
static bool ReindexIsCurrentlyProcessingIndex(Oid indexOid);
static void SetReindexProcessing(Oid heapOid, Oid indexOid);
static void ResetReindexProcessing(void);
@@ -3479,15 +3480,21 @@ validate_index(Oid heapId, Oid indexId, Snapshot snapshot)
/*
* validate_index_callback - bulkdelete callback to collect the index TIDs
*/
-static bool
-validate_index_callback(ItemPointer itemptr, void *opaque)
+static int
+validate_index_callback(ItemPointer itemptrs, int nitem, bool *deletable,
+ void *opaque)
{
ValidateIndexState *state = (ValidateIndexState *) opaque;
- int64 encoded = itemptr_encode(itemptr);
- tuplesort_putdatum(state->tuplesort, Int64GetDatum(encoded), false);
- state->itups += 1;
- return false; /* never actually delete anything */
+ for (int i = 0; i < nitem; i++)
+ {
+ int64 encoded = itemptr_encode(&(itemptrs[i]));
+
+ tuplesort_putdatum(state->tuplesort, Int64GetDatum(encoded), false);
+ }
+ state->itups += nitem;
+
+ return 0; /* never actually delete anything */
}
/*
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..cc8d458ea89 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -127,7 +127,7 @@ static bool vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
BufferAccessStrategy bstrategy);
static double compute_parallel_delay(void);
static VacOptValue get_vacoptval_from_boolean(DefElem *def);
-static bool vac_tid_reaped(ItemPointer itemptr, void *state);
+static int vac_tid_reaped(ItemPointer itemptrs, int nitem, bool *deletable, void *state);
/*
* GUC check function to ensure GUC value specified is within the allowable
@@ -2654,10 +2654,10 @@ vac_cleanup_one_index(IndexVacuumInfo *ivinfo, IndexBulkDeleteResult *istat)
*
* This has the right signature to be an IndexBulkDeleteCallback.
*/
-static bool
-vac_tid_reaped(ItemPointer itemptr, void *state)
+static int
+vac_tid_reaped(ItemPointer itemptrs, int nitem, bool *deletable, void *state)
{
TidStore *dead_items = (TidStore *) state;
- return TidStoreIsMember(dead_items, itemptr);
+ return TidStoreIsMemberMulti(dead_items, itemptrs, nitem, deletable);
}
diff --git a/src/include/access/genam.h b/src/include/access/genam.h
index 5b2ab181b5f..6f559a1209d 100644
--- a/src/include/access/genam.h
+++ b/src/include/access/genam.h
@@ -107,7 +107,8 @@ typedef struct IndexBulkDeleteResult
} IndexBulkDeleteResult;
/* Typedef for callback function to determine if a tuple is bulk-deletable */
-typedef bool (*IndexBulkDeleteCallback) (ItemPointer itemptr, void *state);
+typedef int (*IndexBulkDeleteCallback) (ItemPointer itemptr, int nitem,
+ bool *deletable, void *state);
/* struct definitions appear in relscan.h */
typedef struct IndexScanDescData *IndexScanDesc;
--
2.43.5