diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index cb28830..26115ca 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -429,6 +429,7 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, vacrel->live_tuples = 0; vacrel->recently_dead_tuples = 0; vacrel->missed_dead_tuples = 0; + vacrel->cutoffs.OldestXmin = InvalidTransactionId; /* * Get cutoffs that determine which deleted tuples are considered DEAD, @@ -446,7 +447,22 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, * want to teach lazy_scan_prune to recompute vistest from time to time, * to increase the number of dead tuples it can prune away.) */ - vacrel->aggressive = vacuum_get_cutoffs(rel, params, &vacrel->cutoffs); + /* If this is a TOAST and we have a horizon from the parent, use it */ + if (params->toast_parent != InvalidOid && params->cached_parent_cutoffs_valid) + { + vacrel->cutoffs.OldestXmin = params->cached_parent_oldest_xmin; + vacrel->aggressive = vacuum_get_cutoffs(rel, params, &vacrel->cutoffs); + } + else + { + vacrel->aggressive = vacuum_get_cutoffs(rel, params, &vacrel->cutoffs); + if (params->toast_parent == InvalidOid) + { + params->cached_parent_oldest_xmin = vacrel->cutoffs.OldestXmin; + params->cached_parent_cutoffs_valid = true; + } + } + vacrel->rel_pages = orig_rel_pages = RelationGetNumberOfBlocks(rel); vacrel->vistest = GlobalVisTestFor(rel); /* Initialize state used to track oldest extant XID/MXID */ diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index c42c8a6..0b8442f 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -628,6 +628,7 @@ vacuum(List *relations, VacuumParams *params, BufferAccessStrategy bstrategy, * to avoid affecting other relations. */ memcpy(¶ms_copy, params, sizeof(VacuumParams)); + params_copy.cached_parent_cutoffs_valid = false; if (!vacuum_rel(vrel->oid, vrel->relation, ¶ms_copy, bstrategy)) continue; @@ -1117,7 +1118,8 @@ vacuum_get_cutoffs(Relation rel, const VacuumParams *params, * that only one vacuum process can be working on a particular table at * any time, and that each vacuum is always an independent transaction. */ - cutoffs->OldestXmin = GetOldestNonRemovableTransactionId(rel); + if (!TransactionIdIsValid(cutoffs->OldestXmin)) + cutoffs->OldestXmin = GetOldestNonRemovableTransactionId(rel); Assert(TransactionIdIsNormal(cutoffs->OldestXmin)); @@ -2297,6 +2299,12 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params, toast_vacuum_params.options |= VACOPT_PROCESS_MAIN; toast_vacuum_params.toast_parent = relid; + if (params->cached_parent_cutoffs_valid) + { + toast_vacuum_params.cached_parent_oldest_xmin = params->cached_parent_oldest_xmin; + toast_vacuum_params.cached_parent_cutoffs_valid = true; + } + vacuum_rel(toast_relid, NULL, &toast_vacuum_params, bstrategy); } @@ -2309,7 +2317,6 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params, return true; } - /* * Open all the vacuumable indexes of the given relation, obtaining the * specified kind of lock on each. Return an array of Relation pointers for diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h index 759f9a8..d5ae2bf 100644 --- a/src/include/commands/vacuum.h +++ b/src/include/commands/vacuum.h @@ -237,6 +237,9 @@ typedef struct VacuumParams * disabled. */ int nworkers; + + bool cached_parent_cutoffs_valid; /* Flag for cache cutoffs to TOAST */ + TransactionId cached_parent_oldest_xmin; } VacuumParams; /*