Separate vacuum cost variables from GUCs
Vacuum code run both by autovacuum workers and a backend doing VACUUM/ANALYZE previously inspected VacuumCostLimit and VacuumCostDelay, which are the global variables backing the GUCs vacuum_cost_limit and vacuum_cost_delay. Autovacuum workers needed to override these variables with their own values, derived from autovacuum_vacuum_cost_limit and autovacuum_vacuum_cost_delay and worker cost limit balancing logic. This led to confusing code which, in some cases, both derived and set a new value of VacuumCostLimit from VacuumCostLimit. In preparation for refreshing these GUC values more often, introduce new, independent global variables and add a function to update them using the GUCs and existing logic. Per suggestion by Kyotaro Horiguchi Author: Melanie Plageman <melanieplageman@gmail.com> Reviewed-by: Masahiko Sawada <sawada.mshk@gmail.com> Reviewed-by: Daniel Gustafsson <daniel@yesql.se> Reviewed-by: Kyotaro Horiguchi <horikyota.ntt@gmail.com> Reviewed-by: Robert Haas <robertmhaas@gmail.com> Discussion: https://www.postgresql.org/message-id/flat/CAAKRu_ZngzqnEODc7LmS1NH04Kt6Y9huSjz5pp7%2BDXhrjDA0gw%40mail.gmail.com
This commit is contained in:
parent
71a825194f
commit
a85c60a945
@ -72,6 +72,15 @@ int vacuum_multixact_freeze_table_age;
|
|||||||
int vacuum_failsafe_age;
|
int vacuum_failsafe_age;
|
||||||
int vacuum_multixact_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
|
* 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.
|
* 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;
|
ListCell *cur;
|
||||||
|
|
||||||
|
VacuumUpdateCosts();
|
||||||
in_vacuum = true;
|
in_vacuum = true;
|
||||||
VacuumCostActive = (VacuumCostDelay > 0);
|
VacuumCostActive = (vacuum_cost_delay > 0);
|
||||||
VacuumCostBalance = 0;
|
VacuumCostBalance = 0;
|
||||||
VacuumPageHit = 0;
|
VacuumPageHit = 0;
|
||||||
VacuumPageMiss = 0;
|
VacuumPageMiss = 0;
|
||||||
@ -2244,14 +2254,14 @@ vacuum_delay_point(void)
|
|||||||
*/
|
*/
|
||||||
if (VacuumSharedCostBalance != NULL)
|
if (VacuumSharedCostBalance != NULL)
|
||||||
msec = compute_parallel_delay();
|
msec = compute_parallel_delay();
|
||||||
else if (VacuumCostBalance >= VacuumCostLimit)
|
else if (VacuumCostBalance >= vacuum_cost_limit)
|
||||||
msec = VacuumCostDelay * VacuumCostBalance / VacuumCostLimit;
|
msec = vacuum_cost_delay * VacuumCostBalance / vacuum_cost_limit;
|
||||||
|
|
||||||
/* Nap if appropriate */
|
/* Nap if appropriate */
|
||||||
if (msec > 0)
|
if (msec > 0)
|
||||||
{
|
{
|
||||||
if (msec > VacuumCostDelay * 4)
|
if (msec > vacuum_cost_delay * 4)
|
||||||
msec = VacuumCostDelay * 4;
|
msec = vacuum_cost_delay * 4;
|
||||||
|
|
||||||
pgstat_report_wait_start(WAIT_EVENT_VACUUM_DELAY);
|
pgstat_report_wait_start(WAIT_EVENT_VACUUM_DELAY);
|
||||||
pg_usleep(msec * 1000);
|
pg_usleep(msec * 1000);
|
||||||
@ -2268,8 +2278,7 @@ vacuum_delay_point(void)
|
|||||||
|
|
||||||
VacuumCostBalance = 0;
|
VacuumCostBalance = 0;
|
||||||
|
|
||||||
/* update balance values for workers */
|
VacuumUpdateCosts();
|
||||||
AutoVacuumUpdateDelay();
|
|
||||||
|
|
||||||
/* Might have gotten an interrupt while sleeping */
|
/* Might have gotten an interrupt while sleeping */
|
||||||
CHECK_FOR_INTERRUPTS();
|
CHECK_FOR_INTERRUPTS();
|
||||||
@ -2319,11 +2328,11 @@ compute_parallel_delay(void)
|
|||||||
/* Compute the total local balance for the current worker */
|
/* Compute the total local balance for the current worker */
|
||||||
VacuumCostBalanceLocal += VacuumCostBalance;
|
VacuumCostBalanceLocal += VacuumCostBalance;
|
||||||
|
|
||||||
if ((shared_balance >= VacuumCostLimit) &&
|
if ((shared_balance >= vacuum_cost_limit) &&
|
||||||
(VacuumCostBalanceLocal > 0.5 * ((double) VacuumCostLimit / nworkers)))
|
(VacuumCostBalanceLocal > 0.5 * ((double) vacuum_cost_limit / nworkers)))
|
||||||
{
|
{
|
||||||
/* Compute sleep time based on the local cost balance */
|
/* 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);
|
pg_atomic_sub_fetch_u32(VacuumSharedCostBalance, VacuumCostBalanceLocal);
|
||||||
VacuumCostBalanceLocal = 0;
|
VacuumCostBalanceLocal = 0;
|
||||||
}
|
}
|
||||||
|
@ -995,7 +995,8 @@ parallel_vacuum_main(dsm_segment *seg, shm_toc *toc)
|
|||||||
false);
|
false);
|
||||||
|
|
||||||
/* Set cost-based vacuum delay */
|
/* Set cost-based vacuum delay */
|
||||||
VacuumCostActive = (VacuumCostDelay > 0);
|
VacuumCostActive = (vacuum_cost_delay > 0);
|
||||||
|
VacuumUpdateCosts();
|
||||||
VacuumCostBalance = 0;
|
VacuumCostBalance = 0;
|
||||||
VacuumPageHit = 0;
|
VacuumPageHit = 0;
|
||||||
VacuumPageMiss = 0;
|
VacuumPageMiss = 0;
|
||||||
|
@ -1773,16 +1773,24 @@ FreeWorkerInfo(int code, Datum arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update the cost-based delay parameters, so that multiple workers consume
|
* Update vacuum cost-based delay-related parameters for autovacuum workers and
|
||||||
* each a fraction of the total available I/O.
|
* 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
|
void
|
||||||
AutoVacuumUpdateDelay(void)
|
VacuumUpdateCosts(void)
|
||||||
{
|
{
|
||||||
if (MyWorkerInfo)
|
if (MyWorkerInfo)
|
||||||
{
|
{
|
||||||
VacuumCostDelay = MyWorkerInfo->wi_cost_delay;
|
vacuum_cost_delay = MyWorkerInfo->wi_cost_delay;
|
||||||
VacuumCostLimit = MyWorkerInfo->wi_cost_limit;
|
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;
|
autovac_table *tab;
|
||||||
bool isshared;
|
bool isshared;
|
||||||
bool skipit;
|
bool skipit;
|
||||||
double stdVacuumCostDelay;
|
|
||||||
int stdVacuumCostLimit;
|
|
||||||
dlist_iter iter;
|
dlist_iter iter;
|
||||||
|
|
||||||
CHECK_FOR_INTERRUPTS();
|
CHECK_FOR_INTERRUPTS();
|
||||||
@ -2415,14 +2421,6 @@ do_autovacuum(void)
|
|||||||
continue;
|
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 */
|
/* Must hold AutovacuumLock while mucking with cost balance info */
|
||||||
LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
|
LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
|
||||||
|
|
||||||
@ -2436,7 +2434,7 @@ do_autovacuum(void)
|
|||||||
autovac_balance_cost();
|
autovac_balance_cost();
|
||||||
|
|
||||||
/* set the active cost parameters from the result of that */
|
/* set the active cost parameters from the result of that */
|
||||||
AutoVacuumUpdateDelay();
|
VacuumUpdateCosts();
|
||||||
|
|
||||||
/* done */
|
/* done */
|
||||||
LWLockRelease(AutovacuumLock);
|
LWLockRelease(AutovacuumLock);
|
||||||
@ -2533,10 +2531,6 @@ deleted:
|
|||||||
MyWorkerInfo->wi_tableoid = InvalidOid;
|
MyWorkerInfo->wi_tableoid = InvalidOid;
|
||||||
MyWorkerInfo->wi_sharedrel = false;
|
MyWorkerInfo->wi_sharedrel = false;
|
||||||
LWLockRelease(AutovacuumScheduleLock);
|
LWLockRelease(AutovacuumScheduleLock);
|
||||||
|
|
||||||
/* restore vacuum cost GUCs for the next iteration */
|
|
||||||
VacuumCostDelay = stdVacuumCostDelay;
|
|
||||||
VacuumCostLimit = stdVacuumCostLimit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -307,6 +307,8 @@ extern PGDLLIMPORT pg_atomic_uint32 *VacuumActiveNWorkers;
|
|||||||
extern PGDLLIMPORT int VacuumCostBalanceLocal;
|
extern PGDLLIMPORT int VacuumCostBalanceLocal;
|
||||||
|
|
||||||
extern PGDLLIMPORT bool VacuumFailsafeActive;
|
extern PGDLLIMPORT bool VacuumFailsafeActive;
|
||||||
|
extern PGDLLIMPORT double vacuum_cost_delay;
|
||||||
|
extern PGDLLIMPORT int vacuum_cost_limit;
|
||||||
|
|
||||||
/* in commands/vacuum.c */
|
/* in commands/vacuum.c */
|
||||||
extern void ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel);
|
extern void ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel);
|
||||||
@ -347,6 +349,9 @@ extern IndexBulkDeleteResult *vac_cleanup_one_index(IndexVacuumInfo *ivinfo,
|
|||||||
IndexBulkDeleteResult *istat);
|
IndexBulkDeleteResult *istat);
|
||||||
extern Size vac_max_items_to_alloc_size(int max_items);
|
extern Size vac_max_items_to_alloc_size(int max_items);
|
||||||
|
|
||||||
|
/* In postmaster/autovacuum.c */
|
||||||
|
extern void VacuumUpdateCosts(void);
|
||||||
|
|
||||||
/* in commands/vacuumparallel.c */
|
/* in commands/vacuumparallel.c */
|
||||||
extern ParallelVacuumState *parallel_vacuum_init(Relation rel, Relation *indrels,
|
extern ParallelVacuumState *parallel_vacuum_init(Relation rel, Relation *indrels,
|
||||||
int nindexes, int nrequested_workers,
|
int nindexes, int nrequested_workers,
|
||||||
|
@ -63,9 +63,6 @@ extern int StartAutoVacWorker(void);
|
|||||||
/* called from postmaster when a worker could not be forked */
|
/* called from postmaster when a worker could not be forked */
|
||||||
extern void AutoVacWorkerFailed(void);
|
extern void AutoVacWorkerFailed(void);
|
||||||
|
|
||||||
/* autovacuum cost-delay balancer */
|
|
||||||
extern void AutoVacuumUpdateDelay(void);
|
|
||||||
|
|
||||||
#ifdef EXEC_BACKEND
|
#ifdef EXEC_BACKEND
|
||||||
extern void AutoVacLauncherMain(int argc, char *argv[]) pg_attribute_noreturn();
|
extern void AutoVacLauncherMain(int argc, char *argv[]) pg_attribute_noreturn();
|
||||||
extern void AutoVacWorkerMain(int argc, char *argv[]) pg_attribute_noreturn();
|
extern void AutoVacWorkerMain(int argc, char *argv[]) pg_attribute_noreturn();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user