Commit 0d831389 authored by Alvaro Herrera's avatar Alvaro Herrera

Rationalize vacuuming options and parameters

We were involving the parser too much in setting up initial vacuuming
parameters.  This patch moves that responsibility elsewhere to simplify
code, and also to make future additions easier.  To do this, create a
new struct VacuumParams which is filled just prior to vacuum execution,
instead of at parse time; for user-invoked vacuuming this is set up in a
new function ExecVacuum, while autovacuum sets it up by itself.

While at it, add a new member VACOPT_SKIPTOAST to enum VacuumOption,
only set by autovacuum, which is used to disable vacuuming of the toast
table instead of the old do_toast parameter; this relieves the argument
list of vacuum() and some callees a bit.  This partially makes up for
having added more arguments in an effort to avoid having autovacuum from
constructing a VacuumStmt parse node.

Author: Michael Paquier. Some tweaks by Álvaro
Reviewed by: Robert Haas, Stephen Frost, Álvaro Herrera
parent 4559167c
...@@ -85,7 +85,7 @@ static MemoryContext anl_context = NULL; ...@@ -85,7 +85,7 @@ static MemoryContext anl_context = NULL;
static BufferAccessStrategy vac_strategy; static BufferAccessStrategy vac_strategy;
static void do_analyze_rel(Relation onerel, VacuumStmt *vacstmt, static void do_analyze_rel(Relation onerel, int options, List *va_cols,
AcquireSampleRowsFunc acquirefunc, BlockNumber relpages, AcquireSampleRowsFunc acquirefunc, BlockNumber relpages,
bool inh, bool in_outer_xact, int elevel); bool inh, bool in_outer_xact, int elevel);
static void BlockSampler_Init(BlockSampler bs, BlockNumber nblocks, static void BlockSampler_Init(BlockSampler bs, BlockNumber nblocks,
...@@ -115,7 +115,7 @@ static Datum ind_fetch_func(VacAttrStatsP stats, int rownum, bool *isNull); ...@@ -115,7 +115,7 @@ static Datum ind_fetch_func(VacAttrStatsP stats, int rownum, bool *isNull);
* analyze_rel() -- analyze one relation * analyze_rel() -- analyze one relation
*/ */
void void
analyze_rel(Oid relid, VacuumStmt *vacstmt, analyze_rel(Oid relid, RangeVar *relation, int options, List *va_cols,
bool in_outer_xact, BufferAccessStrategy bstrategy) bool in_outer_xact, BufferAccessStrategy bstrategy)
{ {
Relation onerel; Relation onerel;
...@@ -124,7 +124,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt, ...@@ -124,7 +124,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
BlockNumber relpages = 0; BlockNumber relpages = 0;
/* Select logging level */ /* Select logging level */
if (vacstmt->options & VACOPT_VERBOSE) if (options & VACOPT_VERBOSE)
elevel = INFO; elevel = INFO;
else else
elevel = DEBUG2; elevel = DEBUG2;
...@@ -144,7 +144,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt, ...@@ -144,7 +144,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
* matter if we ever try to accumulate stats on dead tuples.) If the rel * matter if we ever try to accumulate stats on dead tuples.) If the rel
* has been dropped since we last saw it, we don't need to process it. * has been dropped since we last saw it, we don't need to process it.
*/ */
if (!(vacstmt->options & VACOPT_NOWAIT)) if (!(options & VACOPT_NOWAIT))
onerel = try_relation_open(relid, ShareUpdateExclusiveLock); onerel = try_relation_open(relid, ShareUpdateExclusiveLock);
else if (ConditionalLockRelationOid(relid, ShareUpdateExclusiveLock)) else if (ConditionalLockRelationOid(relid, ShareUpdateExclusiveLock))
onerel = try_relation_open(relid, NoLock); onerel = try_relation_open(relid, NoLock);
...@@ -155,7 +155,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt, ...@@ -155,7 +155,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
ereport(LOG, ereport(LOG,
(errcode(ERRCODE_LOCK_NOT_AVAILABLE), (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
errmsg("skipping analyze of \"%s\" --- lock not available", errmsg("skipping analyze of \"%s\" --- lock not available",
vacstmt->relation->relname))); relation->relname)));
} }
if (!onerel) if (!onerel)
return; return;
...@@ -167,7 +167,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt, ...@@ -167,7 +167,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
(pg_database_ownercheck(MyDatabaseId, GetUserId()) && !onerel->rd_rel->relisshared))) (pg_database_ownercheck(MyDatabaseId, GetUserId()) && !onerel->rd_rel->relisshared)))
{ {
/* No need for a WARNING if we already complained during VACUUM */ /* No need for a WARNING if we already complained during VACUUM */
if (!(vacstmt->options & VACOPT_VACUUM)) if (!(options & VACOPT_VACUUM))
{ {
if (onerel->rd_rel->relisshared) if (onerel->rd_rel->relisshared)
ereport(WARNING, ereport(WARNING,
...@@ -248,7 +248,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt, ...@@ -248,7 +248,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
else else
{ {
/* No need for a WARNING if we already complained during VACUUM */ /* No need for a WARNING if we already complained during VACUUM */
if (!(vacstmt->options & VACOPT_VACUUM)) if (!(options & VACOPT_VACUUM))
ereport(WARNING, ereport(WARNING,
(errmsg("skipping \"%s\" --- cannot analyze non-tables or special system tables", (errmsg("skipping \"%s\" --- cannot analyze non-tables or special system tables",
RelationGetRelationName(onerel)))); RelationGetRelationName(onerel))));
...@@ -266,14 +266,14 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt, ...@@ -266,14 +266,14 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
/* /*
* Do the normal non-recursive ANALYZE. * Do the normal non-recursive ANALYZE.
*/ */
do_analyze_rel(onerel, vacstmt, acquirefunc, relpages, do_analyze_rel(onerel, options, va_cols, acquirefunc, relpages,
false, in_outer_xact, elevel); false, in_outer_xact, elevel);
/* /*
* If there are child tables, do recursive ANALYZE. * If there are child tables, do recursive ANALYZE.
*/ */
if (onerel->rd_rel->relhassubclass) if (onerel->rd_rel->relhassubclass)
do_analyze_rel(onerel, vacstmt, acquirefunc, relpages, do_analyze_rel(onerel, options, va_cols, acquirefunc, relpages,
true, in_outer_xact, elevel); true, in_outer_xact, elevel);
/* /*
...@@ -302,7 +302,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt, ...@@ -302,7 +302,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
* acquirefunc for each child table. * acquirefunc for each child table.
*/ */
static void static void
do_analyze_rel(Relation onerel, VacuumStmt *vacstmt, do_analyze_rel(Relation onerel, int options, List *va_cols,
AcquireSampleRowsFunc acquirefunc, BlockNumber relpages, AcquireSampleRowsFunc acquirefunc, BlockNumber relpages,
bool inh, bool in_outer_xact, int elevel) bool inh, bool in_outer_xact, int elevel)
{ {
...@@ -372,14 +372,14 @@ do_analyze_rel(Relation onerel, VacuumStmt *vacstmt, ...@@ -372,14 +372,14 @@ do_analyze_rel(Relation onerel, VacuumStmt *vacstmt,
* *
* Note that system attributes are never analyzed. * Note that system attributes are never analyzed.
*/ */
if (vacstmt->va_cols != NIL) if (va_cols != NIL)
{ {
ListCell *le; ListCell *le;
vacattrstats = (VacAttrStats **) palloc(list_length(vacstmt->va_cols) * vacattrstats = (VacAttrStats **) palloc(list_length(va_cols) *
sizeof(VacAttrStats *)); sizeof(VacAttrStats *));
tcnt = 0; tcnt = 0;
foreach(le, vacstmt->va_cols) foreach(le, va_cols)
{ {
char *col = strVal(lfirst(le)); char *col = strVal(lfirst(le));
...@@ -436,7 +436,7 @@ do_analyze_rel(Relation onerel, VacuumStmt *vacstmt, ...@@ -436,7 +436,7 @@ do_analyze_rel(Relation onerel, VacuumStmt *vacstmt,
thisdata->indexInfo = indexInfo = BuildIndexInfo(Irel[ind]); thisdata->indexInfo = indexInfo = BuildIndexInfo(Irel[ind]);
thisdata->tupleFract = 1.0; /* fix later if partial */ thisdata->tupleFract = 1.0; /* fix later if partial */
if (indexInfo->ii_Expressions != NIL && vacstmt->va_cols == NIL) if (indexInfo->ii_Expressions != NIL && va_cols == NIL)
{ {
ListCell *indexpr_item = list_head(indexInfo->ii_Expressions); ListCell *indexpr_item = list_head(indexInfo->ii_Expressions);
...@@ -595,7 +595,7 @@ do_analyze_rel(Relation onerel, VacuumStmt *vacstmt, ...@@ -595,7 +595,7 @@ do_analyze_rel(Relation onerel, VacuumStmt *vacstmt,
* VACUUM ANALYZE, don't overwrite the accurate count already inserted by * VACUUM ANALYZE, don't overwrite the accurate count already inserted by
* VACUUM. * VACUUM.
*/ */
if (!inh && !(vacstmt->options & VACOPT_VACUUM)) if (!inh && !(options & VACOPT_VACUUM))
{ {
for (ind = 0; ind < nindexes; ind++) for (ind = 0; ind < nindexes; ind++)
{ {
...@@ -623,7 +623,7 @@ do_analyze_rel(Relation onerel, VacuumStmt *vacstmt, ...@@ -623,7 +623,7 @@ do_analyze_rel(Relation onerel, VacuumStmt *vacstmt,
pgstat_report_analyze(onerel, totalrows, totaldeadrows); pgstat_report_analyze(onerel, totalrows, totaldeadrows);
/* If this isn't part of VACUUM ANALYZE, let index AMs do cleanup */ /* If this isn't part of VACUUM ANALYZE, let index AMs do cleanup */
if (!(vacstmt->options & VACOPT_VACUUM)) if (!(options & VACOPT_VACUUM))
{ {
for (ind = 0; ind < nindexes; ind++) for (ind = 0; ind < nindexes; ind++)
{ {
......
This diff is collapsed.
...@@ -169,7 +169,7 @@ static bool heap_page_is_all_visible(Relation rel, Buffer buf, ...@@ -169,7 +169,7 @@ static bool heap_page_is_all_visible(Relation rel, Buffer buf,
* and locked the relation. * and locked the relation.
*/ */
void void
lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt, lazy_vacuum_rel(Relation onerel, int options, VacuumParams *params,
BufferAccessStrategy bstrategy) BufferAccessStrategy bstrategy)
{ {
LVRelStats *vacrelstats; LVRelStats *vacrelstats;
...@@ -193,6 +193,8 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt, ...@@ -193,6 +193,8 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt,
TransactionId new_frozen_xid; TransactionId new_frozen_xid;
MultiXactId new_min_multi; MultiXactId new_min_multi;
Assert(params != NULL);
/* measure elapsed time iff autovacuum logging requires it */ /* measure elapsed time iff autovacuum logging requires it */
if (IsAutoVacuumWorkerProcess() && Log_autovacuum_min_duration >= 0) if (IsAutoVacuumWorkerProcess() && Log_autovacuum_min_duration >= 0)
{ {
...@@ -200,7 +202,7 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt, ...@@ -200,7 +202,7 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt,
starttime = GetCurrentTimestamp(); starttime = GetCurrentTimestamp();
} }
if (vacstmt->options & VACOPT_VERBOSE) if (options & VACOPT_VERBOSE)
elevel = INFO; elevel = INFO;
else else
elevel = DEBUG2; elevel = DEBUG2;
...@@ -208,9 +210,10 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt, ...@@ -208,9 +210,10 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt,
vac_strategy = bstrategy; vac_strategy = bstrategy;
vacuum_set_xid_limits(onerel, vacuum_set_xid_limits(onerel,
vacstmt->freeze_min_age, vacstmt->freeze_table_age, params->freeze_min_age,
vacstmt->multixact_freeze_min_age, params->freeze_table_age,
vacstmt->multixact_freeze_table_age, params->multixact_freeze_min_age,
params->multixact_freeze_table_age,
&OldestXmin, &FreezeLimit, &xidFullScanLimit, &OldestXmin, &FreezeLimit, &xidFullScanLimit,
&MultiXactCutoff, &mxactFullScanLimit); &MultiXactCutoff, &mxactFullScanLimit);
......
...@@ -3300,10 +3300,6 @@ _copyVacuumStmt(const VacuumStmt *from) ...@@ -3300,10 +3300,6 @@ _copyVacuumStmt(const VacuumStmt *from)
VacuumStmt *newnode = makeNode(VacuumStmt); VacuumStmt *newnode = makeNode(VacuumStmt);
COPY_SCALAR_FIELD(options); COPY_SCALAR_FIELD(options);
COPY_SCALAR_FIELD(freeze_min_age);
COPY_SCALAR_FIELD(freeze_table_age);
COPY_SCALAR_FIELD(multixact_freeze_min_age);
COPY_SCALAR_FIELD(multixact_freeze_table_age);
COPY_NODE_FIELD(relation); COPY_NODE_FIELD(relation);
COPY_NODE_FIELD(va_cols); COPY_NODE_FIELD(va_cols);
......
...@@ -1503,10 +1503,6 @@ static bool ...@@ -1503,10 +1503,6 @@ static bool
_equalVacuumStmt(const VacuumStmt *a, const VacuumStmt *b) _equalVacuumStmt(const VacuumStmt *a, const VacuumStmt *b)
{ {
COMPARE_SCALAR_FIELD(options); COMPARE_SCALAR_FIELD(options);
COMPARE_SCALAR_FIELD(freeze_min_age);
COMPARE_SCALAR_FIELD(freeze_table_age);
COMPARE_SCALAR_FIELD(multixact_freeze_min_age);
COMPARE_SCALAR_FIELD(multixact_freeze_table_age);
COMPARE_NODE_FIELD(relation); COMPARE_NODE_FIELD(relation);
COMPARE_NODE_FIELD(va_cols); COMPARE_NODE_FIELD(va_cols);
......
...@@ -9034,12 +9034,10 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose ...@@ -9034,12 +9034,10 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
n->options = VACOPT_VACUUM; n->options = VACOPT_VACUUM;
if ($2) if ($2)
n->options |= VACOPT_FULL; n->options |= VACOPT_FULL;
if ($3)
n->options |= VACOPT_FREEZE;
if ($4) if ($4)
n->options |= VACOPT_VERBOSE; n->options |= VACOPT_VERBOSE;
n->freeze_min_age = $3 ? 0 : -1;
n->freeze_table_age = $3 ? 0 : -1;
n->multixact_freeze_min_age = $3 ? 0 : -1;
n->multixact_freeze_table_age = $3 ? 0 : -1;
n->relation = NULL; n->relation = NULL;
n->va_cols = NIL; n->va_cols = NIL;
$$ = (Node *)n; $$ = (Node *)n;
...@@ -9050,12 +9048,10 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose ...@@ -9050,12 +9048,10 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
n->options = VACOPT_VACUUM; n->options = VACOPT_VACUUM;
if ($2) if ($2)
n->options |= VACOPT_FULL; n->options |= VACOPT_FULL;
if ($3)
n->options |= VACOPT_FREEZE;
if ($4) if ($4)
n->options |= VACOPT_VERBOSE; n->options |= VACOPT_VERBOSE;
n->freeze_min_age = $3 ? 0 : -1;
n->freeze_table_age = $3 ? 0 : -1;
n->multixact_freeze_min_age = $3 ? 0 : -1;
n->multixact_freeze_table_age = $3 ? 0 : -1;
n->relation = $5; n->relation = $5;
n->va_cols = NIL; n->va_cols = NIL;
$$ = (Node *)n; $$ = (Node *)n;
...@@ -9066,30 +9062,16 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose ...@@ -9066,30 +9062,16 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
n->options |= VACOPT_VACUUM; n->options |= VACOPT_VACUUM;
if ($2) if ($2)
n->options |= VACOPT_FULL; n->options |= VACOPT_FULL;
if ($3)
n->options |= VACOPT_FREEZE;
if ($4) if ($4)
n->options |= VACOPT_VERBOSE; n->options |= VACOPT_VERBOSE;
n->freeze_min_age = $3 ? 0 : -1;
n->freeze_table_age = $3 ? 0 : -1;
n->multixact_freeze_min_age = $3 ? 0 : -1;
n->multixact_freeze_table_age = $3 ? 0 : -1;
$$ = (Node *)n; $$ = (Node *)n;
} }
| VACUUM '(' vacuum_option_list ')' | VACUUM '(' vacuum_option_list ')'
{ {
VacuumStmt *n = makeNode(VacuumStmt); VacuumStmt *n = makeNode(VacuumStmt);
n->options = VACOPT_VACUUM | $3; n->options = VACOPT_VACUUM | $3;
if (n->options & VACOPT_FREEZE)
{
n->freeze_min_age = n->freeze_table_age = 0;
n->multixact_freeze_min_age = 0;
n->multixact_freeze_table_age = 0;
}
else
{
n->freeze_min_age = n->freeze_table_age = -1;
n->multixact_freeze_min_age = -1;
n->multixact_freeze_table_age = -1;
}
n->relation = NULL; n->relation = NULL;
n->va_cols = NIL; n->va_cols = NIL;
$$ = (Node *) n; $$ = (Node *) n;
...@@ -9098,18 +9080,6 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose ...@@ -9098,18 +9080,6 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
{ {
VacuumStmt *n = makeNode(VacuumStmt); VacuumStmt *n = makeNode(VacuumStmt);
n->options = VACOPT_VACUUM | $3; n->options = VACOPT_VACUUM | $3;
if (n->options & VACOPT_FREEZE)
{
n->freeze_min_age = n->freeze_table_age = 0;
n->multixact_freeze_min_age = 0;
n->multixact_freeze_table_age = 0;
}
else
{
n->freeze_min_age = n->freeze_table_age = -1;
n->multixact_freeze_min_age = -1;
n->multixact_freeze_table_age = -1;
}
n->relation = $5; n->relation = $5;
n->va_cols = $6; n->va_cols = $6;
if (n->va_cols != NIL) /* implies analyze */ if (n->va_cols != NIL) /* implies analyze */
...@@ -9137,10 +9107,6 @@ AnalyzeStmt: ...@@ -9137,10 +9107,6 @@ AnalyzeStmt:
n->options = VACOPT_ANALYZE; n->options = VACOPT_ANALYZE;
if ($2) if ($2)
n->options |= VACOPT_VERBOSE; n->options |= VACOPT_VERBOSE;
n->freeze_min_age = -1;
n->freeze_table_age = -1;
n->multixact_freeze_min_age = -1;
n->multixact_freeze_table_age = -1;
n->relation = NULL; n->relation = NULL;
n->va_cols = NIL; n->va_cols = NIL;
$$ = (Node *)n; $$ = (Node *)n;
...@@ -9151,10 +9117,6 @@ AnalyzeStmt: ...@@ -9151,10 +9117,6 @@ AnalyzeStmt:
n->options = VACOPT_ANALYZE; n->options = VACOPT_ANALYZE;
if ($2) if ($2)
n->options |= VACOPT_VERBOSE; n->options |= VACOPT_VERBOSE;
n->freeze_min_age = -1;
n->freeze_table_age = -1;
n->multixact_freeze_min_age = -1;
n->multixact_freeze_table_age = -1;
n->relation = $3; n->relation = $3;
n->va_cols = $4; n->va_cols = $4;
$$ = (Node *)n; $$ = (Node *)n;
......
...@@ -184,16 +184,11 @@ typedef struct av_relation ...@@ -184,16 +184,11 @@ typedef struct av_relation
typedef struct autovac_table typedef struct autovac_table
{ {
Oid at_relid; Oid at_relid;
bool at_dovacuum; int at_vacoptions; /* bitmask of VacuumOption */
bool at_doanalyze; VacuumParams at_params;
int at_freeze_min_age;
int at_freeze_table_age;
int at_multixact_freeze_min_age;
int at_multixact_freeze_table_age;
int at_vacuum_cost_delay; int at_vacuum_cost_delay;
int at_vacuum_cost_limit; int at_vacuum_cost_limit;
bool at_dobalance; bool at_dobalance;
bool at_wraparound;
char *at_relname; char *at_relname;
char *at_nspname; char *at_nspname;
char *at_datname; char *at_datname;
...@@ -2301,7 +2296,7 @@ do_autovacuum(void) ...@@ -2301,7 +2296,7 @@ do_autovacuum(void)
* next table in our list. * next table in our list.
*/ */
HOLD_INTERRUPTS(); HOLD_INTERRUPTS();
if (tab->at_dovacuum) if (tab->at_vacoptions & VACOPT_VACUUM)
errcontext("automatic vacuum of table \"%s.%s.%s\"", errcontext("automatic vacuum of table \"%s.%s.%s\"",
tab->at_datname, tab->at_nspname, tab->at_relname); tab->at_datname, tab->at_nspname, tab->at_relname);
else else
...@@ -2528,15 +2523,17 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, ...@@ -2528,15 +2523,17 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
tab = palloc(sizeof(autovac_table)); tab = palloc(sizeof(autovac_table));
tab->at_relid = relid; tab->at_relid = relid;
tab->at_dovacuum = dovacuum; tab->at_vacoptions = VACOPT_SKIPTOAST |
tab->at_doanalyze = doanalyze; (dovacuum ? VACOPT_VACUUM : 0) |
tab->at_freeze_min_age = freeze_min_age; (doanalyze ? VACOPT_ANALYZE : 0) |
tab->at_freeze_table_age = freeze_table_age; (wraparound ? VACOPT_NOWAIT : 0);
tab->at_multixact_freeze_min_age = multixact_freeze_min_age; tab->at_params.freeze_min_age = freeze_min_age;
tab->at_multixact_freeze_table_age = multixact_freeze_table_age; tab->at_params.freeze_table_age = freeze_table_age;
tab->at_params.multixact_freeze_min_age = multixact_freeze_min_age;
tab->at_params.multixact_freeze_table_age = multixact_freeze_table_age;
tab->at_params.is_wraparound = wraparound;
tab->at_vacuum_cost_limit = vac_cost_limit; tab->at_vacuum_cost_limit = vac_cost_limit;
tab->at_vacuum_cost_delay = vac_cost_delay; tab->at_vacuum_cost_delay = vac_cost_delay;
tab->at_wraparound = wraparound;
tab->at_relname = NULL; tab->at_relname = NULL;
tab->at_nspname = NULL; tab->at_nspname = NULL;
tab->at_datname = NULL; tab->at_datname = NULL;
...@@ -2737,39 +2734,22 @@ relation_needs_vacanalyze(Oid relid, ...@@ -2737,39 +2734,22 @@ relation_needs_vacanalyze(Oid relid,
* Vacuum and/or analyze the specified table * Vacuum and/or analyze the specified table
*/ */
static void static void
autovacuum_do_vac_analyze(autovac_table *tab, autovacuum_do_vac_analyze(autovac_table *tab, BufferAccessStrategy bstrategy)
BufferAccessStrategy bstrategy)
{ {
VacuumStmt vacstmt; RangeVar rangevar;
RangeVar rangevar;
/* Set up command parameters --- use local variables instead of palloc */ /* Set up command parameters --- use local variables instead of palloc */
MemSet(&vacstmt, 0, sizeof(vacstmt));
MemSet(&rangevar, 0, sizeof(rangevar)); MemSet(&rangevar, 0, sizeof(rangevar));
rangevar.schemaname = tab->at_nspname; rangevar.schemaname = tab->at_nspname;
rangevar.relname = tab->at_relname; rangevar.relname = tab->at_relname;
rangevar.location = -1; rangevar.location = -1;
vacstmt.type = T_VacuumStmt;
if (!tab->at_wraparound)
vacstmt.options = VACOPT_NOWAIT;
if (tab->at_dovacuum)
vacstmt.options |= VACOPT_VACUUM;
if (tab->at_doanalyze)
vacstmt.options |= VACOPT_ANALYZE;
vacstmt.freeze_min_age = tab->at_freeze_min_age;
vacstmt.freeze_table_age = tab->at_freeze_table_age;
vacstmt.multixact_freeze_min_age = tab->at_multixact_freeze_min_age;
vacstmt.multixact_freeze_table_age = tab->at_multixact_freeze_table_age;
/* we pass the OID, but might need this anyway for an error message */
vacstmt.relation = &rangevar;
vacstmt.va_cols = NIL;
/* Let pgstat know what we're doing */ /* Let pgstat know what we're doing */
autovac_report_activity(tab); autovac_report_activity(tab);
vacuum(&vacstmt, tab->at_relid, false, bstrategy, tab->at_wraparound, true); vacuum(tab->at_vacoptions, &rangevar, tab->at_relid, &tab->at_params, NIL,
bstrategy, true);
} }
/* /*
...@@ -2791,10 +2771,10 @@ autovac_report_activity(autovac_table *tab) ...@@ -2791,10 +2771,10 @@ autovac_report_activity(autovac_table *tab)
int len; int len;
/* Report the command and possible options */ /* Report the command and possible options */
if (tab->at_dovacuum) if (tab->at_vacoptions & VACOPT_VACUUM)
snprintf(activity, MAX_AUTOVAC_ACTIV_LEN, snprintf(activity, MAX_AUTOVAC_ACTIV_LEN,
"autovacuum: VACUUM%s", "autovacuum: VACUUM%s",
tab->at_doanalyze ? " ANALYZE" : ""); tab->at_vacoptions & VACOPT_ANALYZE ? " ANALYZE" : "");
else else
snprintf(activity, MAX_AUTOVAC_ACTIV_LEN, snprintf(activity, MAX_AUTOVAC_ACTIV_LEN,
"autovacuum: ANALYZE"); "autovacuum: ANALYZE");
...@@ -2806,7 +2786,7 @@ autovac_report_activity(autovac_table *tab) ...@@ -2806,7 +2786,7 @@ autovac_report_activity(autovac_table *tab)
snprintf(activity + len, MAX_AUTOVAC_ACTIV_LEN - len, snprintf(activity + len, MAX_AUTOVAC_ACTIV_LEN - len,
" %s.%s%s", tab->at_nspname, tab->at_relname, " %s.%s%s", tab->at_nspname, tab->at_relname,
tab->at_wraparound ? " (to prevent wraparound)" : ""); tab->at_params.is_wraparound ? " (to prevent wraparound)" : "");
/* Set statement_timestamp() to current time for pg_stat_activity */ /* Set statement_timestamp() to current time for pg_stat_activity */
SetCurrentStatementStartTimestamp(); SetCurrentStatementStartTimestamp();
......
...@@ -627,7 +627,7 @@ standard_ProcessUtility(Node *parsetree, ...@@ -627,7 +627,7 @@ standard_ProcessUtility(Node *parsetree,
/* we choose to allow this during "read only" transactions */ /* we choose to allow this during "read only" transactions */
PreventCommandDuringRecovery((stmt->options & VACOPT_VACUUM) ? PreventCommandDuringRecovery((stmt->options & VACOPT_VACUUM) ?
"VACUUM" : "ANALYZE"); "VACUUM" : "ANALYZE");
vacuum(stmt, InvalidOid, true, NULL, false, isTopLevel); ExecVacuum(stmt, isTopLevel);
} }
break; break;
......
...@@ -130,6 +130,19 @@ typedef struct VacAttrStats ...@@ -130,6 +130,19 @@ typedef struct VacAttrStats
int rowstride; int rowstride;
} VacAttrStats; } VacAttrStats;
/*
* Parameters customizing behavior of VACUUM and ANALYZE.
*/
typedef struct VacuumParams
{
int freeze_min_age; /* min freeze age, -1 to use default */
int freeze_table_age; /* age at which to scan whole table */
int multixact_freeze_min_age; /* min multixact freeze age,
* -1 to use default */
int multixact_freeze_table_age; /* multixact age at which to
* scan whole table */
bool is_wraparound; /* force a for-wraparound vacuum */
} VacuumParams;
/* GUC parameters */ /* GUC parameters */
extern PGDLLIMPORT int default_statistics_target; /* PGDLLIMPORT for extern PGDLLIMPORT int default_statistics_target; /* PGDLLIMPORT for
...@@ -141,8 +154,10 @@ extern int vacuum_multixact_freeze_table_age; ...@@ -141,8 +154,10 @@ extern int vacuum_multixact_freeze_table_age;
/* in commands/vacuum.c */ /* in commands/vacuum.c */
extern void vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast, extern void ExecVacuum(VacuumStmt *vacstmt, bool isTopLevel);
BufferAccessStrategy bstrategy, bool for_wraparound, bool isTopLevel); extern void vacuum(int options, RangeVar *relation, Oid relid,
VacuumParams *params, List *va_cols,
BufferAccessStrategy bstrategy, bool isTopLevel);
extern void vac_open_indexes(Relation relation, LOCKMODE lockmode, extern void vac_open_indexes(Relation relation, LOCKMODE lockmode,
int *nindexes, Relation **Irel); int *nindexes, Relation **Irel);
extern void vac_close_indexes(int nindexes, Relation *Irel, LOCKMODE lockmode); extern void vac_close_indexes(int nindexes, Relation *Irel, LOCKMODE lockmode);
...@@ -171,12 +186,13 @@ extern void vac_update_datfrozenxid(void); ...@@ -171,12 +186,13 @@ extern void vac_update_datfrozenxid(void);
extern void vacuum_delay_point(void); extern void vacuum_delay_point(void);
/* in commands/vacuumlazy.c */ /* in commands/vacuumlazy.c */
extern void lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt, extern void lazy_vacuum_rel(Relation onerel, int options,
BufferAccessStrategy bstrategy); VacuumParams *params, BufferAccessStrategy bstrategy);
/* in commands/analyze.c */ /* in commands/analyze.c */
extern void analyze_rel(Oid relid, VacuumStmt *vacstmt, extern void analyze_rel(Oid relid, RangeVar *relation, int options,
bool in_outer_xact, BufferAccessStrategy bstrategy); List *va_cols, bool in_outer_xact,
BufferAccessStrategy bstrategy);
extern bool std_typanalyze(VacAttrStats *stats); extern bool std_typanalyze(VacAttrStats *stats);
extern double anl_random_fract(void); extern double anl_random_fract(void);
extern double anl_init_selection_state(int n); extern double anl_init_selection_state(int n);
......
...@@ -2608,9 +2608,7 @@ typedef struct ClusterStmt ...@@ -2608,9 +2608,7 @@ typedef struct ClusterStmt
* *
* Even though these are nominally two statements, it's convenient to use * Even though these are nominally two statements, it's convenient to use
* just one node type for both. Note that at least one of VACOPT_VACUUM * just one node type for both. Note that at least one of VACOPT_VACUUM
* and VACOPT_ANALYZE must be set in options. VACOPT_FREEZE is an internal * and VACOPT_ANALYZE must be set in options.
* convenience for the grammar and is not examined at runtime --- the
* freeze_min_age and freeze_table_age fields are what matter.
* ---------------------- * ----------------------
*/ */
typedef enum VacuumOption typedef enum VacuumOption
...@@ -2620,19 +2618,14 @@ typedef enum VacuumOption ...@@ -2620,19 +2618,14 @@ typedef enum VacuumOption
VACOPT_VERBOSE = 1 << 2, /* print progress info */ VACOPT_VERBOSE = 1 << 2, /* print progress info */
VACOPT_FREEZE = 1 << 3, /* FREEZE option */ VACOPT_FREEZE = 1 << 3, /* FREEZE option */
VACOPT_FULL = 1 << 4, /* FULL (non-concurrent) vacuum */ VACOPT_FULL = 1 << 4, /* FULL (non-concurrent) vacuum */
VACOPT_NOWAIT = 1 << 5 /* don't wait to get lock (autovacuum only) */ VACOPT_NOWAIT = 1 << 5, /* don't wait to get lock (autovacuum only) */
VACOPT_SKIPTOAST = 1 << 6 /* don't process the TOAST table, if any */
} VacuumOption; } VacuumOption;
typedef struct VacuumStmt typedef struct VacuumStmt
{ {
NodeTag type; NodeTag type;
int options; /* OR of VacuumOption flags */ int options; /* OR of VacuumOption flags */
int freeze_min_age; /* min freeze age, or -1 to use default */
int freeze_table_age; /* age at which to scan whole table */
int multixact_freeze_min_age; /* min multixact freeze age,
* or -1 to use default */
int multixact_freeze_table_age; /* multixact age at which to
* scan whole table */
RangeVar *relation; /* single table to process, or NULL */ RangeVar *relation; /* single table to process, or NULL */
List *va_cols; /* list of column names, or NIL for all */ List *va_cols; /* list of column names, or NIL for all */
} VacuumStmt; } VacuumStmt;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment