mirror of
https://github.com/postgres/postgres.git
synced 2025-11-24 00:23:06 +03:00
Refactor heap_page_prune_and_freeze() parameters into a struct
heap_page_prune_and_freeze() had accumulated an unwieldy number of input parameters and upcoming work to handle VM updates in this function will add even more. Introduce a new PruneFreezeParams struct to group the function’s input parameters, improving readability and maintainability. Author: Melanie Plageman <melanieplageman@gmail.com> Reviewed-by: Kirill Reshke <reshkekirill@gmail.com> Discussion: https://postgr.es/m/yn4zp35kkdsjx6wf47zcfmxgexxt4h2og47pvnw2x5ifyrs3qc%407uw6jyyxuyf7
This commit is contained in:
@@ -261,12 +261,18 @@ heap_page_prune_opt(Relation relation, Buffer buffer)
|
|||||||
PruneFreezeResult presult;
|
PruneFreezeResult presult;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For now, pass mark_unused_now as false regardless of whether or
|
* We don't pass the HEAP_PAGE_PRUNE_MARK_UNUSED_NOW option
|
||||||
* not the relation has indexes, since we cannot safely determine
|
* regardless of whether or not the relation has indexes, since we
|
||||||
* that during on-access pruning with the current implementation.
|
* cannot safely determine that during on-access pruning with the
|
||||||
|
* current implementation.
|
||||||
*/
|
*/
|
||||||
heap_page_prune_and_freeze(relation, buffer, vistest, 0,
|
PruneFreezeParams params = {.relation = relation,.buffer = buffer,
|
||||||
NULL, &presult, PRUNE_ON_ACCESS, &dummy_off_loc, NULL, NULL);
|
.reason = PRUNE_ON_ACCESS,.options = 0,
|
||||||
|
.vistest = vistest,.cutoffs = NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
heap_page_prune_and_freeze(¶ms, &presult, &dummy_off_loc,
|
||||||
|
NULL, NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Report the number of tuples reclaimed to pgstats. This is
|
* Report the number of tuples reclaimed to pgstats. This is
|
||||||
@@ -419,60 +425,44 @@ heap_page_will_freeze(Relation relation, Buffer buffer,
|
|||||||
* also need to account for a reduction in the length of the line pointer
|
* also need to account for a reduction in the length of the line pointer
|
||||||
* array following array truncation by us.
|
* array following array truncation by us.
|
||||||
*
|
*
|
||||||
* If the HEAP_PRUNE_FREEZE option is set, we will also freeze tuples if it's
|
* params contains the input parameters used to control freezing and pruning
|
||||||
* required in order to advance relfrozenxid / relminmxid, or if it's
|
* behavior. See the definition of PruneFreezeParams for more on what each
|
||||||
* considered advantageous for overall system performance to do so now. The
|
* parameter does.
|
||||||
* 'cutoffs', 'presult', 'new_relfrozen_xid' and 'new_relmin_mxid' arguments
|
|
||||||
* are required when freezing. When HEAP_PRUNE_FREEZE option is set, we also
|
|
||||||
* set presult->all_visible and presult->all_frozen on exit, to indicate if
|
|
||||||
* the VM bits can be set. They are always set to false when the
|
|
||||||
* HEAP_PRUNE_FREEZE option is not set, because at the moment only callers
|
|
||||||
* that also freeze need that information.
|
|
||||||
*
|
*
|
||||||
* vistest is used to distinguish whether tuples are DEAD or RECENTLY_DEAD
|
* If the HEAP_PAGE_PRUNE_FREEZE option is set in params, we will freeze
|
||||||
* (see heap_prune_satisfies_vacuum).
|
* tuples if it's required in order to advance relfrozenxid / relminmxid, or
|
||||||
*
|
* if it's considered advantageous for overall system performance to do so
|
||||||
* options:
|
* now. The 'params.cutoffs', 'presult', 'new_relfrozen_xid' and
|
||||||
* MARK_UNUSED_NOW indicates that dead items can be set LP_UNUSED during
|
* 'new_relmin_mxid' arguments are required when freezing. When
|
||||||
* pruning.
|
* HEAP_PAGE_PRUNE_FREEZE option is passed, we also set presult->all_visible
|
||||||
*
|
* and presult->all_frozen on exit, to indicate if the VM bits can be set.
|
||||||
* FREEZE indicates that we will also freeze tuples, and will return
|
* They are always set to false when the HEAP_PAGE_PRUNE_FREEZE option is not
|
||||||
* 'all_visible', 'all_frozen' flags to the caller.
|
* passed, because at the moment only callers that also freeze need that
|
||||||
*
|
* information.
|
||||||
* cutoffs contains the freeze cutoffs, established by VACUUM at the beginning
|
|
||||||
* of vacuuming the relation. Required if HEAP_PRUNE_FREEZE option is set.
|
|
||||||
* cutoffs->OldestXmin is also used to determine if dead tuples are
|
|
||||||
* HEAPTUPLE_RECENTLY_DEAD or HEAPTUPLE_DEAD.
|
|
||||||
*
|
*
|
||||||
* presult contains output parameters needed by callers, such as the number of
|
* presult contains output parameters needed by callers, such as the number of
|
||||||
* tuples removed and the offsets of dead items on the page after pruning.
|
* tuples removed and the offsets of dead items on the page after pruning.
|
||||||
* heap_page_prune_and_freeze() is responsible for initializing it. Required
|
* heap_page_prune_and_freeze() is responsible for initializing it. Required
|
||||||
* by all callers.
|
* by all callers.
|
||||||
*
|
*
|
||||||
* reason indicates why the pruning is performed. It is included in the WAL
|
|
||||||
* record for debugging and analysis purposes, but otherwise has no effect.
|
|
||||||
*
|
|
||||||
* off_loc is the offset location required by the caller to use in error
|
* off_loc is the offset location required by the caller to use in error
|
||||||
* callback.
|
* callback.
|
||||||
*
|
*
|
||||||
* new_relfrozen_xid and new_relmin_mxid must provided by the caller if the
|
* new_relfrozen_xid and new_relmin_mxid must provided by the caller if the
|
||||||
* HEAP_PRUNE_FREEZE option is set. On entry, they contain the oldest XID and
|
* HEAP_PAGE_PRUNE_FREEZE option is set in params. On entry, they contain the
|
||||||
* multi-XID seen on the relation so far. They will be updated with oldest
|
* oldest XID and multi-XID seen on the relation so far. They will be updated
|
||||||
* values present on the page after pruning. After processing the whole
|
* with oldest values present on the page after pruning. After processing the
|
||||||
* relation, VACUUM can use these values as the new relfrozenxid/relminmxid
|
* whole relation, VACUUM can use these values as the new
|
||||||
* for the relation.
|
* relfrozenxid/relminmxid for the relation.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
heap_page_prune_and_freeze(Relation relation, Buffer buffer,
|
heap_page_prune_and_freeze(PruneFreezeParams *params,
|
||||||
GlobalVisState *vistest,
|
|
||||||
int options,
|
|
||||||
struct VacuumCutoffs *cutoffs,
|
|
||||||
PruneFreezeResult *presult,
|
PruneFreezeResult *presult,
|
||||||
PruneReason reason,
|
|
||||||
OffsetNumber *off_loc,
|
OffsetNumber *off_loc,
|
||||||
TransactionId *new_relfrozen_xid,
|
TransactionId *new_relfrozen_xid,
|
||||||
MultiXactId *new_relmin_mxid)
|
MultiXactId *new_relmin_mxid)
|
||||||
{
|
{
|
||||||
|
Buffer buffer = params->buffer;
|
||||||
Page page = BufferGetPage(buffer);
|
Page page = BufferGetPage(buffer);
|
||||||
BlockNumber blockno = BufferGetBlockNumber(buffer);
|
BlockNumber blockno = BufferGetBlockNumber(buffer);
|
||||||
OffsetNumber offnum,
|
OffsetNumber offnum,
|
||||||
@@ -486,10 +476,11 @@ heap_page_prune_and_freeze(Relation relation, Buffer buffer,
|
|||||||
int64 fpi_before = pgWalUsage.wal_fpi;
|
int64 fpi_before = pgWalUsage.wal_fpi;
|
||||||
|
|
||||||
/* Copy parameters to prstate */
|
/* Copy parameters to prstate */
|
||||||
prstate.vistest = vistest;
|
prstate.vistest = params->vistest;
|
||||||
prstate.mark_unused_now = (options & HEAP_PAGE_PRUNE_MARK_UNUSED_NOW) != 0;
|
prstate.mark_unused_now =
|
||||||
prstate.attempt_freeze = (options & HEAP_PAGE_PRUNE_FREEZE) != 0;
|
(params->options & HEAP_PAGE_PRUNE_MARK_UNUSED_NOW) != 0;
|
||||||
prstate.cutoffs = cutoffs;
|
prstate.attempt_freeze = (params->options & HEAP_PAGE_PRUNE_FREEZE) != 0;
|
||||||
|
prstate.cutoffs = params->cutoffs;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Our strategy is to scan the page and make lists of items to change,
|
* Our strategy is to scan the page and make lists of items to change,
|
||||||
@@ -583,7 +574,7 @@ heap_page_prune_and_freeze(Relation relation, Buffer buffer,
|
|||||||
prstate.visibility_cutoff_xid = InvalidTransactionId;
|
prstate.visibility_cutoff_xid = InvalidTransactionId;
|
||||||
|
|
||||||
maxoff = PageGetMaxOffsetNumber(page);
|
maxoff = PageGetMaxOffsetNumber(page);
|
||||||
tup.t_tableOid = RelationGetRelid(relation);
|
tup.t_tableOid = RelationGetRelid(params->relation);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine HTSV for all tuples, and queue them up for processing as HOT
|
* Determine HTSV for all tuples, and queue them up for processing as HOT
|
||||||
@@ -786,7 +777,7 @@ heap_page_prune_and_freeze(Relation relation, Buffer buffer,
|
|||||||
* Decide if we want to go ahead with freezing according to the freeze
|
* Decide if we want to go ahead with freezing according to the freeze
|
||||||
* plans we prepared, or not.
|
* plans we prepared, or not.
|
||||||
*/
|
*/
|
||||||
do_freeze = heap_page_will_freeze(relation, buffer,
|
do_freeze = heap_page_will_freeze(params->relation, buffer,
|
||||||
did_tuple_hint_fpi,
|
did_tuple_hint_fpi,
|
||||||
do_prune,
|
do_prune,
|
||||||
do_hint_prune,
|
do_hint_prune,
|
||||||
@@ -838,7 +829,7 @@ heap_page_prune_and_freeze(Relation relation, Buffer buffer,
|
|||||||
/*
|
/*
|
||||||
* Emit a WAL XLOG_HEAP2_PRUNE* record showing what we did
|
* Emit a WAL XLOG_HEAP2_PRUNE* record showing what we did
|
||||||
*/
|
*/
|
||||||
if (RelationNeedsWAL(relation))
|
if (RelationNeedsWAL(params->relation))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* The snapshotConflictHorizon for the whole record should be the
|
* The snapshotConflictHorizon for the whole record should be the
|
||||||
@@ -876,11 +867,11 @@ heap_page_prune_and_freeze(Relation relation, Buffer buffer,
|
|||||||
else
|
else
|
||||||
conflict_xid = prstate.latest_xid_removed;
|
conflict_xid = prstate.latest_xid_removed;
|
||||||
|
|
||||||
log_heap_prune_and_freeze(relation, buffer,
|
log_heap_prune_and_freeze(params->relation, buffer,
|
||||||
InvalidBuffer, /* vmbuffer */
|
InvalidBuffer, /* vmbuffer */
|
||||||
0, /* vmflags */
|
0, /* vmflags */
|
||||||
conflict_xid,
|
conflict_xid,
|
||||||
true, reason,
|
true, params->reason,
|
||||||
prstate.frozen, prstate.nfrozen,
|
prstate.frozen, prstate.nfrozen,
|
||||||
prstate.redirected, prstate.nredirected,
|
prstate.redirected, prstate.nredirected,
|
||||||
prstate.nowdead, prstate.ndead,
|
prstate.nowdead, prstate.ndead,
|
||||||
|
|||||||
@@ -1965,7 +1965,10 @@ lazy_scan_prune(LVRelState *vacrel,
|
|||||||
{
|
{
|
||||||
Relation rel = vacrel->rel;
|
Relation rel = vacrel->rel;
|
||||||
PruneFreezeResult presult;
|
PruneFreezeResult presult;
|
||||||
int prune_options = 0;
|
PruneFreezeParams params = {.relation = rel,.buffer = buf,
|
||||||
|
.reason = PRUNE_VACUUM_SCAN,.options = HEAP_PAGE_PRUNE_FREEZE,
|
||||||
|
.vistest = vacrel->vistest,.cutoffs = &vacrel->cutoffs
|
||||||
|
};
|
||||||
|
|
||||||
Assert(BufferGetBlockNumber(buf) == blkno);
|
Assert(BufferGetBlockNumber(buf) == blkno);
|
||||||
|
|
||||||
@@ -1984,12 +1987,11 @@ lazy_scan_prune(LVRelState *vacrel,
|
|||||||
* tuples. Pruning will have determined whether or not the page is
|
* tuples. Pruning will have determined whether or not the page is
|
||||||
* all-visible.
|
* all-visible.
|
||||||
*/
|
*/
|
||||||
prune_options = HEAP_PAGE_PRUNE_FREEZE;
|
|
||||||
if (vacrel->nindexes == 0)
|
if (vacrel->nindexes == 0)
|
||||||
prune_options |= HEAP_PAGE_PRUNE_MARK_UNUSED_NOW;
|
params.options |= HEAP_PAGE_PRUNE_MARK_UNUSED_NOW;
|
||||||
|
|
||||||
heap_page_prune_and_freeze(rel, buf, vacrel->vistest, prune_options,
|
heap_page_prune_and_freeze(¶ms,
|
||||||
&vacrel->cutoffs, &presult, PRUNE_VACUUM_SCAN,
|
&presult,
|
||||||
&vacrel->offnum,
|
&vacrel->offnum,
|
||||||
&vacrel->NewRelfrozenXid, &vacrel->NewRelminMxid);
|
&vacrel->NewRelfrozenXid, &vacrel->NewRelminMxid);
|
||||||
|
|
||||||
|
|||||||
@@ -221,6 +221,56 @@ typedef struct HeapPageFreeze
|
|||||||
|
|
||||||
} HeapPageFreeze;
|
} HeapPageFreeze;
|
||||||
|
|
||||||
|
|
||||||
|
/* 'reason' codes for heap_page_prune_and_freeze() */
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
PRUNE_ON_ACCESS, /* on-access pruning */
|
||||||
|
PRUNE_VACUUM_SCAN, /* VACUUM 1st heap pass */
|
||||||
|
PRUNE_VACUUM_CLEANUP, /* VACUUM 2nd heap pass */
|
||||||
|
} PruneReason;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Input parameters to heap_page_prune_and_freeze()
|
||||||
|
*/
|
||||||
|
typedef struct PruneFreezeParams
|
||||||
|
{
|
||||||
|
Relation relation; /* relation containing buffer to be pruned */
|
||||||
|
Buffer buffer; /* buffer to be pruned */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The reason pruning was performed. It is used to set the WAL record
|
||||||
|
* opcode which is used for debugging and analysis purposes.
|
||||||
|
*/
|
||||||
|
PruneReason reason;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Contains flag bits:
|
||||||
|
*
|
||||||
|
* HEAP_PAGE_PRUNE_MARK_UNUSED_NOW indicates that dead items can be set
|
||||||
|
* LP_UNUSED during pruning.
|
||||||
|
*
|
||||||
|
* HEAP_PAGE_PRUNE_FREEZE indicates that we will also freeze tuples, and
|
||||||
|
* will return 'all_visible', 'all_frozen' flags to the caller.
|
||||||
|
*/
|
||||||
|
int options;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* vistest is used to distinguish whether tuples are DEAD or RECENTLY_DEAD
|
||||||
|
* (see heap_prune_satisfies_vacuum).
|
||||||
|
*/
|
||||||
|
GlobalVisState *vistest;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Contains the cutoffs used for freezing. They are required if the
|
||||||
|
* HEAP_PAGE_PRUNE_FREEZE option is set. cutoffs->OldestXmin is also used
|
||||||
|
* to determine if dead tuples are HEAPTUPLE_RECENTLY_DEAD or
|
||||||
|
* HEAPTUPLE_DEAD. Currently only vacuum passes in cutoffs. Vacuum
|
||||||
|
* calculates them once, at the beginning of vacuuming the relation.
|
||||||
|
*/
|
||||||
|
struct VacuumCutoffs *cutoffs;
|
||||||
|
} PruneFreezeParams;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Per-page state returned by heap_page_prune_and_freeze()
|
* Per-page state returned by heap_page_prune_and_freeze()
|
||||||
*/
|
*/
|
||||||
@@ -264,13 +314,6 @@ typedef struct PruneFreezeResult
|
|||||||
OffsetNumber deadoffsets[MaxHeapTuplesPerPage];
|
OffsetNumber deadoffsets[MaxHeapTuplesPerPage];
|
||||||
} PruneFreezeResult;
|
} PruneFreezeResult;
|
||||||
|
|
||||||
/* 'reason' codes for heap_page_prune_and_freeze() */
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
PRUNE_ON_ACCESS, /* on-access pruning */
|
|
||||||
PRUNE_VACUUM_SCAN, /* VACUUM 1st heap pass */
|
|
||||||
PRUNE_VACUUM_CLEANUP, /* VACUUM 2nd heap pass */
|
|
||||||
} PruneReason;
|
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* function prototypes for heap access method
|
* function prototypes for heap access method
|
||||||
@@ -367,12 +410,8 @@ extern TransactionId heap_index_delete_tuples(Relation rel,
|
|||||||
|
|
||||||
/* in heap/pruneheap.c */
|
/* in heap/pruneheap.c */
|
||||||
extern void heap_page_prune_opt(Relation relation, Buffer buffer);
|
extern void heap_page_prune_opt(Relation relation, Buffer buffer);
|
||||||
extern void heap_page_prune_and_freeze(Relation relation, Buffer buffer,
|
extern void heap_page_prune_and_freeze(PruneFreezeParams *params,
|
||||||
GlobalVisState *vistest,
|
|
||||||
int options,
|
|
||||||
struct VacuumCutoffs *cutoffs,
|
|
||||||
PruneFreezeResult *presult,
|
PruneFreezeResult *presult,
|
||||||
PruneReason reason,
|
|
||||||
OffsetNumber *off_loc,
|
OffsetNumber *off_loc,
|
||||||
TransactionId *new_relfrozen_xid,
|
TransactionId *new_relfrozen_xid,
|
||||||
MultiXactId *new_relmin_mxid);
|
MultiXactId *new_relmin_mxid);
|
||||||
|
|||||||
@@ -2348,6 +2348,7 @@ ProjectionPath
|
|||||||
PromptInterruptContext
|
PromptInterruptContext
|
||||||
ProtocolVersion
|
ProtocolVersion
|
||||||
PrsStorage
|
PrsStorage
|
||||||
|
PruneFreezeParams
|
||||||
PruneFreezeResult
|
PruneFreezeResult
|
||||||
PruneReason
|
PruneReason
|
||||||
PruneState
|
PruneState
|
||||||
|
|||||||
Reference in New Issue
Block a user