From 17e183835a968e81daf7b74a4164b243e2de35aa Mon Sep 17 00:00:00 2001 From: Melanie Plageman Date: Fri, 29 Mar 2024 19:43:09 -0400 Subject: [PATCH v11 3/7] Introduce PRUNE_DO_* actions We will eventually take additional actions in heap_page_prune() at the discretion of the caller. For now, introduce these PRUNE_DO_* macros and turn mark_unused_now, a paramter to heap_page_prune(), into a PRUNE_DO_ action. --- src/backend/access/heap/pruneheap.c | 51 ++++++++++++++-------------- src/backend/access/heap/vacuumlazy.c | 11 ++++-- src/include/access/heapam.h | 13 ++++++- 3 files changed, 46 insertions(+), 29 deletions(-) diff --git a/src/backend/access/heap/pruneheap.c b/src/backend/access/heap/pruneheap.c index fb0ad834f1b..30965c3c5a1 100644 --- a/src/backend/access/heap/pruneheap.c +++ b/src/backend/access/heap/pruneheap.c @@ -29,10 +29,11 @@ /* Working data for heap_page_prune and subroutines */ typedef struct { + /* PRUNE_DO_* arguments */ + uint8 actions; + /* tuple visibility test, initialized for the relation */ GlobalVisState *vistest; - /* whether or not dead items can be set LP_UNUSED during pruning */ - bool mark_unused_now; TransactionId new_prune_xid; /* new prune hint value for page */ TransactionId snapshotConflictHorizon; /* latest xid removed */ @@ -166,11 +167,12 @@ heap_page_prune_opt(Relation relation, Buffer buffer) PruneResult presult; /* - * For now, pass mark_unused_now as false regardless of whether or - * not the relation has indexes, since we cannot safely determine - * that during on-access pruning with the current implementation. + * For now, do not set PRUNE_DO_MARK_UNUSED_NOW regardless of + * whether or not the relation has indexes, since we cannot safely + * determine that during on-access pruning with the current + * implementation. */ - heap_page_prune(relation, buffer, vistest, false, + heap_page_prune(relation, buffer, vistest, 0, &presult, PRUNE_ON_ACCESS, &dummy_off_loc); /* @@ -215,8 +217,7 @@ heap_page_prune_opt(Relation relation, Buffer buffer) * vistest is used to distinguish whether tuples are DEAD or RECENTLY_DEAD * (see heap_prune_satisfies_vacuum). * - * mark_unused_now indicates whether or not dead items can be set LP_UNUSED - * during pruning. + * actions are the pruning actions that heap_page_prune() should take. * * presult contains output parameters needed by callers such as the number of * tuples removed and the number of line pointers newly marked LP_DEAD. @@ -231,7 +232,7 @@ heap_page_prune_opt(Relation relation, Buffer buffer) void heap_page_prune(Relation relation, Buffer buffer, GlobalVisState *vistest, - bool mark_unused_now, + uint8 actions, PruneResult *presult, PruneReason reason, OffsetNumber *off_loc) @@ -256,7 +257,7 @@ heap_page_prune(Relation relation, Buffer buffer, */ prstate.new_prune_xid = InvalidTransactionId; prstate.vistest = vistest; - prstate.mark_unused_now = mark_unused_now; + prstate.actions = actions; prstate.snapshotConflictHorizon = InvalidTransactionId; prstate.nredirected = prstate.ndead = prstate.nunused = 0; prstate.ndeleted = 0; @@ -320,10 +321,10 @@ heap_page_prune(Relation relation, Buffer buffer, if (ItemIdIsDead(itemid)) { /* - * If the caller set mark_unused_now true, we can set dead line - * pointers LP_UNUSED now. + * If the caller set PRUNE_DO_MARK_UNUSED_NOW, we can set dead + * line pointers LP_UNUSED now. */ - if (unlikely(prstate.mark_unused_now)) + if (unlikely(prstate.actions & PRUNE_DO_MARK_UNUSED_NOW)) heap_prune_record_unused(&prstate, offnum, false); else heap_prune_record_unchanged_lp_dead(page, &prstate, offnum); @@ -822,22 +823,22 @@ heap_prune_record_dead(PruneState *prstate, OffsetNumber offnum, } /* - * Depending on whether or not the caller set mark_unused_now to true, record that a - * line pointer should be marked LP_DEAD or LP_UNUSED. There are other cases in - * which we will mark line pointers LP_UNUSED, but we will not mark line - * pointers LP_DEAD if mark_unused_now is true. + * Depending on whether or not the caller set PRUNE_DO_MARK_UNUSED_NOW, record + * that a line pointer should be marked LP_DEAD or LP_UNUSED. There are other + * cases in which we will mark line pointers LP_UNUSED, but we will not mark + * line pointers LP_DEAD if PRUNE_DO_MARK_UNUSED_NOW is set. */ static void heap_prune_record_dead_or_unused(PruneState *prstate, OffsetNumber offnum, bool was_normal) { /* - * If the caller set mark_unused_now to true, we can remove dead tuples + * If the caller set PRUNE_DO_MARK_UNUSED_NOW, we can remove dead tuples * during pruning instead of marking their line pointers dead. Set this * tuple's line pointer LP_UNUSED. We hint that this option is less * likely. */ - if (unlikely(prstate->mark_unused_now)) + if (unlikely(prstate->actions & PRUNE_DO_MARK_UNUSED_NOW)) heap_prune_record_unused(prstate, offnum, was_normal); else heap_prune_record_dead(prstate, offnum, was_normal); @@ -1080,12 +1081,12 @@ heap_page_prune_execute(Buffer buffer, bool lp_truncate_only, else { /* - * When heap_page_prune() was called, mark_unused_now may have - * been passed as true, which allows would-be LP_DEAD items to be - * made LP_UNUSED instead. This is only possible if the relation - * has no indexes. If there are any dead items, then - * mark_unused_now was not true and every item being marked - * LP_UNUSED must refer to a heap-only tuple. + * When heap_page_prune() was called, PRUNE_DO_MARK_UNUSED_NOW may + * have been set, which allows would-be LP_DEAD items to be made + * LP_UNUSED instead. This is only possible if the relation has + * no indexes. If there are any dead items, then + * PRUNE_DO_MARK_UNUSED_NOW was not set and every item being + * marked LP_UNUSED must refer to a heap-only tuple. */ if (ndead > 0) { diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index ba5b7083a3a..880a218cb4d 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -1425,6 +1425,7 @@ lazy_scan_prune(LVRelState *vacrel, bool all_visible, all_frozen; TransactionId visibility_cutoff_xid; + uint8 actions = 0; int64 fpi_before = pgWalUsage.wal_fpi; OffsetNumber deadoffsets[MaxHeapTuplesPerPage]; HeapTupleFreeze frozen[MaxHeapTuplesPerPage]; @@ -1458,10 +1459,14 @@ lazy_scan_prune(LVRelState *vacrel, * that were deleted from indexes. * * If the relation has no indexes, we can immediately mark would-be dead - * items LP_UNUSED, so mark_unused_now should be true if no indexes and - * false otherwise. + * items LP_UNUSED, so PRUNE_DO_MARK_UNUSED_NOW should be set if no + * indexes and unset otherwise. */ - heap_page_prune(rel, buf, vacrel->vistest, vacrel->nindexes == 0, + + if (vacrel->nindexes == 0) + actions |= PRUNE_DO_MARK_UNUSED_NOW; + + heap_page_prune(rel, buf, vacrel->vistest, actions, &presult, PRUNE_VACUUM_SCAN, &vacrel->offnum); /* diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h index 32a3fbce961..35b8486c34a 100644 --- a/src/include/access/heapam.h +++ b/src/include/access/heapam.h @@ -191,6 +191,17 @@ typedef struct HeapPageFreeze } HeapPageFreeze; +/* + * Actions that can be taken during pruning and freezing. By default, we will + * at least attempt regular pruning. + */ + +/* + * PRUNE_DO_MARK_UNUSED_NOW indicates whether or not dead items can be set + * LP_UNUSED during pruning. + */ +#define PRUNE_DO_MARK_UNUSED_NOW (1 << 1) + /* * Per-page state returned from pruning */ @@ -331,7 +342,7 @@ struct GlobalVisState; extern void heap_page_prune_opt(Relation relation, Buffer buffer); extern void heap_page_prune(Relation relation, Buffer buffer, struct GlobalVisState *vistest, - bool mark_unused_now, + uint8 actions, PruneResult *presult, PruneReason reason, OffsetNumber *off_loc); -- 2.39.2