diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index 7fc5c19e37..f2be74cdb5 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -72,6 +72,15 @@ int vacuum_multixact_freeze_table_age; int vacuum_failsafe_age; int vacuum_multixact_failsafe_age; +/* + * Variables for cost-based vacuum delay. The defaults differ between + * autovacuum and vacuum. They should be set with the appropriate GUC value in + * vacuum code. They are initialized here to the defaults for client backends + * executing VACUUM or ANALYZE. + */ +double vacuum_cost_delay = 0; +int vacuum_cost_limit = 200; + /* * VacuumFailsafeActive is a defined as a global so that we can determine * whether or not to re-enable cost-based vacuum delay when vacuuming a table. @@ -514,8 +523,9 @@ vacuum(List *relations, VacuumParams *params, BufferAccessStrategy bstrategy, { ListCell *cur; + VacuumUpdateCosts(); in_vacuum = true; - VacuumCostActive = (VacuumCostDelay > 0); + VacuumCostActive = (vacuum_cost_delay > 0); VacuumCostBalance = 0; VacuumPageHit = 0; VacuumPageMiss = 0; @@ -2244,14 +2254,14 @@ vacuum_delay_point(void) */ if (VacuumSharedCostBalance != NULL) msec = compute_parallel_delay(); - else if (VacuumCostBalance >= VacuumCostLimit) - msec = VacuumCostDelay * VacuumCostBalance / VacuumCostLimit; + else if (VacuumCostBalance >= vacuum_cost_limit) + msec = vacuum_cost_delay * VacuumCostBalance / vacuum_cost_limit; /* Nap if appropriate */ if (msec > 0) { - if (msec > VacuumCostDelay * 4) - msec = VacuumCostDelay * 4; + if (msec > vacuum_cost_delay * 4) + msec = vacuum_cost_delay * 4; pgstat_report_wait_start(WAIT_EVENT_VACUUM_DELAY); pg_usleep(msec * 1000); @@ -2268,8 +2278,7 @@ vacuum_delay_point(void) VacuumCostBalance = 0; - /* update balance values for workers */ - AutoVacuumUpdateDelay(); + VacuumUpdateCosts(); /* Might have gotten an interrupt while sleeping */ CHECK_FOR_INTERRUPTS(); @@ -2319,11 +2328,11 @@ compute_parallel_delay(void) /* Compute the total local balance for the current worker */ VacuumCostBalanceLocal += VacuumCostBalance; - if ((shared_balance >= VacuumCostLimit) && - (VacuumCostBalanceLocal > 0.5 * ((double) VacuumCostLimit / nworkers))) + if ((shared_balance >= vacuum_cost_limit) && + (VacuumCostBalanceLocal > 0.5 * ((double) vacuum_cost_limit / nworkers))) { /* Compute sleep time based on the local cost balance */ - msec = VacuumCostDelay * VacuumCostBalanceLocal / VacuumCostLimit; + msec = vacuum_cost_delay * VacuumCostBalanceLocal / vacuum_cost_limit; pg_atomic_sub_fetch_u32(VacuumSharedCostBalance, VacuumCostBalanceLocal); VacuumCostBalanceLocal = 0; } diff --git a/src/backend/commands/vacuumparallel.c b/src/backend/commands/vacuumparallel.c index 563117a8f6..cc0aff7904 100644 --- a/src/backend/commands/vacuumparallel.c +++ b/src/backend/commands/vacuumparallel.c @@ -995,7 +995,8 @@ parallel_vacuum_main(dsm_segment *seg, shm_toc *toc) false); /* Set cost-based vacuum delay */ - VacuumCostActive = (VacuumCostDelay > 0); + VacuumCostActive = (vacuum_cost_delay > 0); + VacuumUpdateCosts(); VacuumCostBalance = 0; VacuumPageHit = 0; VacuumPageMiss = 0; diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index c1e911b1b3..0e7933c34d 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -1773,16 +1773,24 @@ FreeWorkerInfo(int code, Datum arg) } /* - * Update the cost-based delay parameters, so that multiple workers consume - * each a fraction of the total available I/O. + * Update vacuum cost-based delay-related parameters for autovacuum workers and + * backends executing VACUUM or ANALYZE using the value of relevant GUCs and + * global state. This must be called during setup for vacuum and after every + * config reload to ensure up-to-date values. */ void -AutoVacuumUpdateDelay(void) +VacuumUpdateCosts(void) { if (MyWorkerInfo) { - VacuumCostDelay = MyWorkerInfo->wi_cost_delay; - VacuumCostLimit = MyWorkerInfo->wi_cost_limit; + vacuum_cost_delay = MyWorkerInfo->wi_cost_delay; + vacuum_cost_limit = MyWorkerInfo->wi_cost_limit; + } + else + { + /* Must be explicit VACUUM or ANALYZE */ + vacuum_cost_delay = VacuumCostDelay; + vacuum_cost_limit = VacuumCostLimit; } } @@ -2311,8 +2319,6 @@ do_autovacuum(void) autovac_table *tab; bool isshared; bool skipit; - double stdVacuumCostDelay; - int stdVacuumCostLimit; dlist_iter iter; CHECK_FOR_INTERRUPTS(); @@ -2415,14 +2421,6 @@ do_autovacuum(void) continue; } - /* - * Remember the prevailing values of the vacuum cost GUCs. We have to - * restore these at the bottom of the loop, else we'll compute wrong - * values in the next iteration of autovac_balance_cost(). - */ - stdVacuumCostDelay = VacuumCostDelay; - stdVacuumCostLimit = VacuumCostLimit; - /* Must hold AutovacuumLock while mucking with cost balance info */ LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE); @@ -2436,7 +2434,7 @@ do_autovacuum(void) autovac_balance_cost(); /* set the active cost parameters from the result of that */ - AutoVacuumUpdateDelay(); + VacuumUpdateCosts(); /* done */ LWLockRelease(AutovacuumLock); @@ -2533,10 +2531,6 @@ deleted: MyWorkerInfo->wi_tableoid = InvalidOid; MyWorkerInfo->wi_sharedrel = false; LWLockRelease(AutovacuumScheduleLock); - - /* restore vacuum cost GUCs for the next iteration */ - VacuumCostDelay = stdVacuumCostDelay; - VacuumCostLimit = stdVacuumCostLimit; } /* diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h index 1223d15e0d..50caf1315d 100644 --- a/src/include/commands/vacuum.h +++ b/src/include/commands/vacuum.h @@ -307,6 +307,8 @@ extern PGDLLIMPORT pg_atomic_uint32 *VacuumActiveNWorkers; extern PGDLLIMPORT int VacuumCostBalanceLocal; extern PGDLLIMPORT bool VacuumFailsafeActive; +extern PGDLLIMPORT double vacuum_cost_delay; +extern PGDLLIMPORT int vacuum_cost_limit; /* in commands/vacuum.c */ extern void ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel); @@ -347,6 +349,9 @@ extern IndexBulkDeleteResult *vac_cleanup_one_index(IndexVacuumInfo *ivinfo, IndexBulkDeleteResult *istat); extern Size vac_max_items_to_alloc_size(int max_items); +/* In postmaster/autovacuum.c */ +extern void VacuumUpdateCosts(void); + /* in commands/vacuumparallel.c */ extern ParallelVacuumState *parallel_vacuum_init(Relation rel, Relation *indrels, int nindexes, int nrequested_workers, diff --git a/src/include/postmaster/autovacuum.h b/src/include/postmaster/autovacuum.h index c140371b51..65afd1ea1e 100644 --- a/src/include/postmaster/autovacuum.h +++ b/src/include/postmaster/autovacuum.h @@ -63,9 +63,6 @@ extern int StartAutoVacWorker(void); /* called from postmaster when a worker could not be forked */ extern void AutoVacWorkerFailed(void); -/* autovacuum cost-delay balancer */ -extern void AutoVacuumUpdateDelay(void); - #ifdef EXEC_BACKEND extern void AutoVacLauncherMain(int argc, char *argv[]) pg_attribute_noreturn(); extern void AutoVacWorkerMain(int argc, char *argv[]) pg_attribute_noreturn();