mirror of
https://github.com/postgres/postgres.git
synced 2025-04-27 22:56:53 +03:00
Add PROCESS_MAIN to VACUUM
Disabling this option is useful to run VACUUM (with or without FULL) on only the toast table of a relation, bypassing the main relation. This option is enabled by default. Running directly VACUUM on a toast table was already possible without this feature, by using the non-deterministic name of a toast relation (as of pg_toast.pg_toast_N, where N would be the OID of the parent relation) in the VACUUM command, and it required a scan of pg_class to know the name of the toast table. So this feature is basically a shortcut to be able to run VACUUM or VACUUM FULL on a toast relation, using only the name of the parent relation. A new switch called --no-process-main is added to vacuumdb, to work as an equivalent of PROCESS_MAIN. Regression tests are added to cover VACUUM and VACUUM FULL, looking at pg_stat_all_tables.vacuum_count to see how many vacuums have run on each table, main or toast. Author: Nathan Bossart Reviewed-by: Masahiko Sawada Discussion: https://postgr.es/m/20221230000028.GA435655@nathanxps13
This commit is contained in:
parent
46d490ac19
commit
4211fbd841
@ -33,6 +33,7 @@ VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ ANALYZE ] [ <replaceable class="paramet
|
|||||||
DISABLE_PAGE_SKIPPING [ <replaceable class="parameter">boolean</replaceable> ]
|
DISABLE_PAGE_SKIPPING [ <replaceable class="parameter">boolean</replaceable> ]
|
||||||
SKIP_LOCKED [ <replaceable class="parameter">boolean</replaceable> ]
|
SKIP_LOCKED [ <replaceable class="parameter">boolean</replaceable> ]
|
||||||
INDEX_CLEANUP { AUTO | ON | OFF }
|
INDEX_CLEANUP { AUTO | ON | OFF }
|
||||||
|
PROCESS_MAIN [ <replaceable class="parameter">boolean</replaceable> ]
|
||||||
PROCESS_TOAST [ <replaceable class="parameter">boolean</replaceable> ]
|
PROCESS_TOAST [ <replaceable class="parameter">boolean</replaceable> ]
|
||||||
TRUNCATE [ <replaceable class="parameter">boolean</replaceable> ]
|
TRUNCATE [ <replaceable class="parameter">boolean</replaceable> ]
|
||||||
PARALLEL <replaceable class="parameter">integer</replaceable>
|
PARALLEL <replaceable class="parameter">integer</replaceable>
|
||||||
@ -238,6 +239,18 @@ VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ ANALYZE ] [ <replaceable class="paramet
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><literal>PROCESS_MAIN</literal></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Specifies that <command>VACUUM</command> should attempt to process the
|
||||||
|
main relation. This is usually the desired behavior and is the default.
|
||||||
|
Setting this option to false may be useful when it is only necessary to
|
||||||
|
vacuum a relation's corresponding <literal>TOAST</literal> table.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><literal>PROCESS_TOAST</literal></term>
|
<term><literal>PROCESS_TOAST</literal></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
@ -317,6 +317,21 @@ PostgreSQL documentation
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--no-process-main</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Skip the main relation.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
This option is only available for servers running
|
||||||
|
<productname>PostgreSQL</productname> 16 and later.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--no-process-toast</option></term>
|
<term><option>--no-process-toast</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
@ -115,6 +115,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
|
|||||||
bool freeze = false;
|
bool freeze = false;
|
||||||
bool full = false;
|
bool full = false;
|
||||||
bool disable_page_skipping = false;
|
bool disable_page_skipping = false;
|
||||||
|
bool process_main = true;
|
||||||
bool process_toast = true;
|
bool process_toast = true;
|
||||||
bool skip_database_stats = false;
|
bool skip_database_stats = false;
|
||||||
bool only_database_stats = false;
|
bool only_database_stats = false;
|
||||||
@ -168,6 +169,8 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
|
|||||||
params.index_cleanup = get_vacoptval_from_boolean(opt);
|
params.index_cleanup = get_vacoptval_from_boolean(opt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (strcmp(opt->defname, "process_main") == 0)
|
||||||
|
process_main = defGetBoolean(opt);
|
||||||
else if (strcmp(opt->defname, "process_toast") == 0)
|
else if (strcmp(opt->defname, "process_toast") == 0)
|
||||||
process_toast = defGetBoolean(opt);
|
process_toast = defGetBoolean(opt);
|
||||||
else if (strcmp(opt->defname, "truncate") == 0)
|
else if (strcmp(opt->defname, "truncate") == 0)
|
||||||
@ -224,6 +227,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
|
|||||||
(freeze ? VACOPT_FREEZE : 0) |
|
(freeze ? VACOPT_FREEZE : 0) |
|
||||||
(full ? VACOPT_FULL : 0) |
|
(full ? VACOPT_FULL : 0) |
|
||||||
(disable_page_skipping ? VACOPT_DISABLE_PAGE_SKIPPING : 0) |
|
(disable_page_skipping ? VACOPT_DISABLE_PAGE_SKIPPING : 0) |
|
||||||
|
(process_main ? VACOPT_PROCESS_MAIN : 0) |
|
||||||
(process_toast ? VACOPT_PROCESS_TOAST : 0) |
|
(process_toast ? VACOPT_PROCESS_TOAST : 0) |
|
||||||
(skip_database_stats ? VACOPT_SKIP_DATABASE_STATS : 0) |
|
(skip_database_stats ? VACOPT_SKIP_DATABASE_STATS : 0) |
|
||||||
(only_database_stats ? VACOPT_ONLY_DATABASE_STATS : 0);
|
(only_database_stats ? VACOPT_ONLY_DATABASE_STATS : 0);
|
||||||
@ -367,9 +371,10 @@ vacuum(List *relations, VacuumParams *params,
|
|||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
errmsg("ONLY_DATABASE_STATS cannot be specified with a list of tables")));
|
errmsg("ONLY_DATABASE_STATS cannot be specified with a list of tables")));
|
||||||
/* don't require people to turn off PROCESS_TOAST explicitly */
|
/* don't require people to turn off PROCESS_TOAST/MAIN explicitly */
|
||||||
if (params->options & ~(VACOPT_VACUUM |
|
if (params->options & ~(VACOPT_VACUUM |
|
||||||
VACOPT_VERBOSE |
|
VACOPT_VERBOSE |
|
||||||
|
VACOPT_PROCESS_MAIN |
|
||||||
VACOPT_PROCESS_TOAST |
|
VACOPT_PROCESS_TOAST |
|
||||||
VACOPT_ONLY_DATABASE_STATS))
|
VACOPT_ONLY_DATABASE_STATS))
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
@ -2031,10 +2036,12 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params, bool skip_privs)
|
|||||||
/*
|
/*
|
||||||
* Remember the relation's TOAST relation for later, if the caller asked
|
* Remember the relation's TOAST relation for later, if the caller asked
|
||||||
* us to process it. In VACUUM FULL, though, the toast table is
|
* us to process it. In VACUUM FULL, though, the toast table is
|
||||||
* automatically rebuilt by cluster_rel so we shouldn't recurse to it.
|
* automatically rebuilt by cluster_rel so we shouldn't recurse to it,
|
||||||
|
* unless PROCESS_MAIN is disabled.
|
||||||
*/
|
*/
|
||||||
if ((params->options & VACOPT_PROCESS_TOAST) != 0 &&
|
if ((params->options & VACOPT_PROCESS_TOAST) != 0 &&
|
||||||
(params->options & VACOPT_FULL) == 0)
|
((params->options & VACOPT_FULL) == 0 ||
|
||||||
|
(params->options & VACOPT_PROCESS_MAIN) == 0))
|
||||||
toast_relid = rel->rd_rel->reltoastrelid;
|
toast_relid = rel->rd_rel->reltoastrelid;
|
||||||
else
|
else
|
||||||
toast_relid = InvalidOid;
|
toast_relid = InvalidOid;
|
||||||
@ -2053,7 +2060,8 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params, bool skip_privs)
|
|||||||
/*
|
/*
|
||||||
* Do the actual work --- either FULL or "lazy" vacuum
|
* Do the actual work --- either FULL or "lazy" vacuum
|
||||||
*/
|
*/
|
||||||
if (params->options & VACOPT_FULL)
|
if ((params->options & VACOPT_FULL) &&
|
||||||
|
(params->options & VACOPT_PROCESS_MAIN))
|
||||||
{
|
{
|
||||||
ClusterParams cluster_params = {0};
|
ClusterParams cluster_params = {0};
|
||||||
|
|
||||||
@ -2067,7 +2075,7 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params, bool skip_privs)
|
|||||||
/* VACUUM FULL is now a variant of CLUSTER; see cluster.c */
|
/* VACUUM FULL is now a variant of CLUSTER; see cluster.c */
|
||||||
cluster_rel(relid, InvalidOid, &cluster_params);
|
cluster_rel(relid, InvalidOid, &cluster_params);
|
||||||
}
|
}
|
||||||
else
|
else if (params->options & VACOPT_PROCESS_MAIN)
|
||||||
table_relation_vacuum(rel, params, vac_strategy);
|
table_relation_vacuum(rel, params, vac_strategy);
|
||||||
|
|
||||||
/* Roll back any GUC changes executed by index functions */
|
/* Roll back any GUC changes executed by index functions */
|
||||||
@ -2094,7 +2102,15 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params, bool skip_privs)
|
|||||||
* totally unimportant for toast relations.
|
* totally unimportant for toast relations.
|
||||||
*/
|
*/
|
||||||
if (toast_relid != InvalidOid)
|
if (toast_relid != InvalidOid)
|
||||||
vacuum_rel(toast_relid, NULL, params, true);
|
{
|
||||||
|
VacuumParams toast_vacuum_params;
|
||||||
|
|
||||||
|
/* force VACOPT_PROCESS_MAIN so vacuum_rel() processes it */
|
||||||
|
memcpy(&toast_vacuum_params, params, sizeof(VacuumParams));
|
||||||
|
toast_vacuum_params.options |= VACOPT_PROCESS_MAIN;
|
||||||
|
|
||||||
|
vacuum_rel(toast_relid, NULL, &toast_vacuum_params, true);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now release the session-level lock on the main table.
|
* Now release the session-level lock on the main table.
|
||||||
|
@ -2860,7 +2860,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
|
|||||||
* skip vac_update_datfrozenxid(); we'll do that separately.
|
* skip vac_update_datfrozenxid(); we'll do that separately.
|
||||||
*/
|
*/
|
||||||
tab->at_params.options =
|
tab->at_params.options =
|
||||||
(dovacuum ? (VACOPT_VACUUM | VACOPT_SKIP_DATABASE_STATS) : 0) |
|
(dovacuum ? (VACOPT_VACUUM |
|
||||||
|
VACOPT_PROCESS_MAIN |
|
||||||
|
VACOPT_SKIP_DATABASE_STATS) : 0) |
|
||||||
(doanalyze ? VACOPT_ANALYZE : 0) |
|
(doanalyze ? VACOPT_ANALYZE : 0) |
|
||||||
(!wraparound ? VACOPT_SKIP_LOCKED : 0);
|
(!wraparound ? VACOPT_SKIP_LOCKED : 0);
|
||||||
|
|
||||||
|
@ -4618,10 +4618,10 @@ psql_completion(const char *text, int start, int end)
|
|||||||
if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
|
if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
|
||||||
COMPLETE_WITH("FULL", "FREEZE", "ANALYZE", "VERBOSE",
|
COMPLETE_WITH("FULL", "FREEZE", "ANALYZE", "VERBOSE",
|
||||||
"DISABLE_PAGE_SKIPPING", "SKIP_LOCKED",
|
"DISABLE_PAGE_SKIPPING", "SKIP_LOCKED",
|
||||||
"INDEX_CLEANUP", "PROCESS_TOAST",
|
"INDEX_CLEANUP", "PROCESS_MAIN", "PROCESS_TOAST",
|
||||||
"TRUNCATE", "PARALLEL", "SKIP_DATABASE_STATS",
|
"TRUNCATE", "PARALLEL", "SKIP_DATABASE_STATS",
|
||||||
"ONLY_DATABASE_STATS");
|
"ONLY_DATABASE_STATS");
|
||||||
else if (TailMatches("FULL|FREEZE|ANALYZE|VERBOSE|DISABLE_PAGE_SKIPPING|SKIP_LOCKED|PROCESS_TOAST|TRUNCATE|SKIP_DATABASE_STATS|ONLY_DATABASE_STATS"))
|
else if (TailMatches("FULL|FREEZE|ANALYZE|VERBOSE|DISABLE_PAGE_SKIPPING|SKIP_LOCKED|PROCESS_MAIN|PROCESS_TOAST|TRUNCATE|SKIP_DATABASE_STATS|ONLY_DATABASE_STATS"))
|
||||||
COMPLETE_WITH("ON", "OFF");
|
COMPLETE_WITH("ON", "OFF");
|
||||||
else if (TailMatches("INDEX_CLEANUP"))
|
else if (TailMatches("INDEX_CLEANUP"))
|
||||||
COMPLETE_WITH("AUTO", "ON", "OFF");
|
COMPLETE_WITH("AUTO", "ON", "OFF");
|
||||||
|
@ -65,6 +65,13 @@ $node->issues_sql_like(
|
|||||||
$node->command_fails(
|
$node->command_fails(
|
||||||
[ 'vacuumdb', '--analyze-only', '--no-truncate', 'postgres' ],
|
[ 'vacuumdb', '--analyze-only', '--no-truncate', 'postgres' ],
|
||||||
'--analyze-only and --no-truncate specified together');
|
'--analyze-only and --no-truncate specified together');
|
||||||
|
$node->issues_sql_like(
|
||||||
|
[ 'vacuumdb', '--no-process-main', 'postgres' ],
|
||||||
|
qr/statement: VACUUM \(PROCESS_MAIN FALSE, SKIP_DATABASE_STATS\).*;/,
|
||||||
|
'vacuumdb --no-process-main');
|
||||||
|
$node->command_fails(
|
||||||
|
[ 'vacuumdb', '--analyze-only', '--no-process-main', 'postgres' ],
|
||||||
|
'--analyze-only and --no-process_main specified together');
|
||||||
$node->issues_sql_like(
|
$node->issues_sql_like(
|
||||||
[ 'vacuumdb', '--no-process-toast', 'postgres' ],
|
[ 'vacuumdb', '--no-process-toast', 'postgres' ],
|
||||||
qr/statement: VACUUM \(PROCESS_TOAST FALSE, SKIP_DATABASE_STATS\).*;/,
|
qr/statement: VACUUM \(PROCESS_TOAST FALSE, SKIP_DATABASE_STATS\).*;/,
|
||||||
|
@ -43,6 +43,7 @@ typedef struct vacuumingOptions
|
|||||||
bool no_index_cleanup;
|
bool no_index_cleanup;
|
||||||
bool force_index_cleanup;
|
bool force_index_cleanup;
|
||||||
bool do_truncate;
|
bool do_truncate;
|
||||||
|
bool process_main;
|
||||||
bool process_toast;
|
bool process_toast;
|
||||||
bool skip_database_stats;
|
bool skip_database_stats;
|
||||||
} vacuumingOptions;
|
} vacuumingOptions;
|
||||||
@ -121,6 +122,7 @@ main(int argc, char *argv[])
|
|||||||
{"force-index-cleanup", no_argument, NULL, 9},
|
{"force-index-cleanup", no_argument, NULL, 9},
|
||||||
{"no-truncate", no_argument, NULL, 10},
|
{"no-truncate", no_argument, NULL, 10},
|
||||||
{"no-process-toast", no_argument, NULL, 11},
|
{"no-process-toast", no_argument, NULL, 11},
|
||||||
|
{"no-process-main", no_argument, NULL, 12},
|
||||||
{NULL, 0, NULL, 0}
|
{NULL, 0, NULL, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -148,6 +150,7 @@ main(int argc, char *argv[])
|
|||||||
vacopts.no_index_cleanup = false;
|
vacopts.no_index_cleanup = false;
|
||||||
vacopts.force_index_cleanup = false;
|
vacopts.force_index_cleanup = false;
|
||||||
vacopts.do_truncate = true;
|
vacopts.do_truncate = true;
|
||||||
|
vacopts.process_main = true;
|
||||||
vacopts.process_toast = true;
|
vacopts.process_toast = true;
|
||||||
|
|
||||||
pg_logging_init(argv[0]);
|
pg_logging_init(argv[0]);
|
||||||
@ -260,6 +263,9 @@ main(int argc, char *argv[])
|
|||||||
case 11:
|
case 11:
|
||||||
vacopts.process_toast = false;
|
vacopts.process_toast = false;
|
||||||
break;
|
break;
|
||||||
|
case 12:
|
||||||
|
vacopts.process_main = false;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
/* getopt_long already emitted a complaint */
|
/* getopt_long already emitted a complaint */
|
||||||
pg_log_error_hint("Try \"%s --help\" for more information.", progname);
|
pg_log_error_hint("Try \"%s --help\" for more information.", progname);
|
||||||
@ -312,6 +318,9 @@ main(int argc, char *argv[])
|
|||||||
if (!vacopts.do_truncate)
|
if (!vacopts.do_truncate)
|
||||||
pg_fatal("cannot use the \"%s\" option when performing only analyze",
|
pg_fatal("cannot use the \"%s\" option when performing only analyze",
|
||||||
"no-truncate");
|
"no-truncate");
|
||||||
|
if (!vacopts.process_main)
|
||||||
|
pg_fatal("cannot use the \"%s\" option when performing only analyze",
|
||||||
|
"no-process-main");
|
||||||
if (!vacopts.process_toast)
|
if (!vacopts.process_toast)
|
||||||
pg_fatal("cannot use the \"%s\" option when performing only analyze",
|
pg_fatal("cannot use the \"%s\" option when performing only analyze",
|
||||||
"no-process-toast");
|
"no-process-toast");
|
||||||
@ -508,6 +517,13 @@ vacuum_one_database(ConnParams *cparams,
|
|||||||
"no-truncate", "12");
|
"no-truncate", "12");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!vacopts->process_main && PQserverVersion(conn) < 160000)
|
||||||
|
{
|
||||||
|
PQfinish(conn);
|
||||||
|
pg_fatal("cannot use the \"%s\" option on server versions older than PostgreSQL %s",
|
||||||
|
"no-process-main", "16");
|
||||||
|
}
|
||||||
|
|
||||||
if (!vacopts->process_toast && PQserverVersion(conn) < 140000)
|
if (!vacopts->process_toast && PQserverVersion(conn) < 140000)
|
||||||
{
|
{
|
||||||
PQfinish(conn);
|
PQfinish(conn);
|
||||||
@ -976,6 +992,13 @@ prepare_vacuum_command(PQExpBuffer sql, int serverVersion,
|
|||||||
appendPQExpBuffer(sql, "%sTRUNCATE FALSE", sep);
|
appendPQExpBuffer(sql, "%sTRUNCATE FALSE", sep);
|
||||||
sep = comma;
|
sep = comma;
|
||||||
}
|
}
|
||||||
|
if (!vacopts->process_main)
|
||||||
|
{
|
||||||
|
/* PROCESS_MAIN is supported since v16 */
|
||||||
|
Assert(serverVersion >= 160000);
|
||||||
|
appendPQExpBuffer(sql, "%sPROCESS_MAIN FALSE", sep);
|
||||||
|
sep = comma;
|
||||||
|
}
|
||||||
if (!vacopts->process_toast)
|
if (!vacopts->process_toast)
|
||||||
{
|
{
|
||||||
/* PROCESS_TOAST is supported since v14 */
|
/* PROCESS_TOAST is supported since v14 */
|
||||||
@ -1090,6 +1113,7 @@ help(const char *progname)
|
|||||||
printf(_(" --min-mxid-age=MXID_AGE minimum multixact ID age of tables to vacuum\n"));
|
printf(_(" --min-mxid-age=MXID_AGE minimum multixact ID age of tables to vacuum\n"));
|
||||||
printf(_(" --min-xid-age=XID_AGE minimum transaction ID age of tables to vacuum\n"));
|
printf(_(" --min-xid-age=XID_AGE minimum transaction ID age of tables to vacuum\n"));
|
||||||
printf(_(" --no-index-cleanup don't remove index entries that point to dead tuples\n"));
|
printf(_(" --no-index-cleanup don't remove index entries that point to dead tuples\n"));
|
||||||
|
printf(_(" --no-process-main skip the main relation\n"));
|
||||||
printf(_(" --no-process-toast skip the TOAST table associated with the table to vacuum\n"));
|
printf(_(" --no-process-toast skip the TOAST table associated with the table to vacuum\n"));
|
||||||
printf(_(" --no-truncate don't truncate empty pages at the end of the table\n"));
|
printf(_(" --no-truncate don't truncate empty pages at the end of the table\n"));
|
||||||
printf(_(" -n, --schema=PATTERN vacuum tables in the specified schema(s) only\n"));
|
printf(_(" -n, --schema=PATTERN vacuum tables in the specified schema(s) only\n"));
|
||||||
|
@ -186,10 +186,11 @@ typedef struct VacAttrStats
|
|||||||
#define VACOPT_FREEZE 0x08 /* FREEZE option */
|
#define VACOPT_FREEZE 0x08 /* FREEZE option */
|
||||||
#define VACOPT_FULL 0x10 /* FULL (non-concurrent) vacuum */
|
#define VACOPT_FULL 0x10 /* FULL (non-concurrent) vacuum */
|
||||||
#define VACOPT_SKIP_LOCKED 0x20 /* skip if cannot get lock */
|
#define VACOPT_SKIP_LOCKED 0x20 /* skip if cannot get lock */
|
||||||
#define VACOPT_PROCESS_TOAST 0x40 /* process the TOAST table, if any */
|
#define VACOPT_PROCESS_MAIN 0x40 /* process main relation */
|
||||||
#define VACOPT_DISABLE_PAGE_SKIPPING 0x80 /* don't skip any pages */
|
#define VACOPT_PROCESS_TOAST 0x80 /* process the TOAST table, if any */
|
||||||
#define VACOPT_SKIP_DATABASE_STATS 0x100 /* skip vac_update_datfrozenxid() */
|
#define VACOPT_DISABLE_PAGE_SKIPPING 0x100 /* don't skip any pages */
|
||||||
#define VACOPT_ONLY_DATABASE_STATS 0x200 /* only vac_update_datfrozenxid() */
|
#define VACOPT_SKIP_DATABASE_STATS 0x200 /* skip vac_update_datfrozenxid() */
|
||||||
|
#define VACOPT_ONLY_DATABASE_STATS 0x400 /* only vac_update_datfrozenxid() */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Values used by index_cleanup and truncate params.
|
* Values used by index_cleanup and truncate params.
|
||||||
|
@ -281,7 +281,8 @@ CREATE TABLE vac_option_tab (a INT, t TEXT);
|
|||||||
INSERT INTO vac_option_tab SELECT a, 't' || a FROM generate_series(1, 10) AS a;
|
INSERT INTO vac_option_tab SELECT a, 't' || a FROM generate_series(1, 10) AS a;
|
||||||
ALTER TABLE vac_option_tab ALTER COLUMN t SET STORAGE EXTERNAL;
|
ALTER TABLE vac_option_tab ALTER COLUMN t SET STORAGE EXTERNAL;
|
||||||
-- Check the number of vacuums done on table vac_option_tab and on its
|
-- Check the number of vacuums done on table vac_option_tab and on its
|
||||||
-- toast relation, to check that PROCESS_TOAST works on what it should.
|
-- toast relation, to check that PROCESS_TOAST and PROCESS_MAIN work on
|
||||||
|
-- what they should.
|
||||||
CREATE VIEW vac_option_tab_counts AS
|
CREATE VIEW vac_option_tab_counts AS
|
||||||
SELECT CASE WHEN c.relname IS NULL
|
SELECT CASE WHEN c.relname IS NULL
|
||||||
THEN 'main' ELSE 'toast' END as rel,
|
THEN 'main' ELSE 'toast' END as rel,
|
||||||
@ -308,6 +309,47 @@ SELECT * FROM vac_option_tab_counts;
|
|||||||
|
|
||||||
VACUUM (PROCESS_TOAST FALSE, FULL) vac_option_tab; -- error
|
VACUUM (PROCESS_TOAST FALSE, FULL) vac_option_tab; -- error
|
||||||
ERROR: PROCESS_TOAST required with VACUUM FULL
|
ERROR: PROCESS_TOAST required with VACUUM FULL
|
||||||
|
-- PROCESS_MAIN option
|
||||||
|
-- Only the toast table is processed.
|
||||||
|
VACUUM (PROCESS_MAIN FALSE) vac_option_tab;
|
||||||
|
SELECT * FROM vac_option_tab_counts;
|
||||||
|
rel | vacuum_count
|
||||||
|
-------+--------------
|
||||||
|
main | 2
|
||||||
|
toast | 2
|
||||||
|
(2 rows)
|
||||||
|
|
||||||
|
-- Nothing is processed.
|
||||||
|
VACUUM (PROCESS_MAIN FALSE, PROCESS_TOAST FALSE) vac_option_tab;
|
||||||
|
SELECT * FROM vac_option_tab_counts;
|
||||||
|
rel | vacuum_count
|
||||||
|
-------+--------------
|
||||||
|
main | 2
|
||||||
|
toast | 2
|
||||||
|
(2 rows)
|
||||||
|
|
||||||
|
-- Check if the filenodes nodes have been updated as wanted after FULL.
|
||||||
|
SELECT relfilenode AS main_filenode FROM pg_class
|
||||||
|
WHERE relname = 'vac_option_tab' \gset
|
||||||
|
SELECT t.relfilenode AS toast_filenode FROM pg_class c, pg_class t
|
||||||
|
WHERE c.reltoastrelid = t.oid AND c.relname = 'vac_option_tab' \gset
|
||||||
|
-- Only the toast relation is processed.
|
||||||
|
VACUUM (PROCESS_MAIN FALSE, FULL) vac_option_tab;
|
||||||
|
SELECT relfilenode = :main_filenode AS is_same_main_filenode
|
||||||
|
FROM pg_class WHERE relname = 'vac_option_tab';
|
||||||
|
is_same_main_filenode
|
||||||
|
-----------------------
|
||||||
|
t
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT t.relfilenode = :toast_filenode AS is_same_toast_filenode
|
||||||
|
FROM pg_class c, pg_class t
|
||||||
|
WHERE c.reltoastrelid = t.oid AND c.relname = 'vac_option_tab';
|
||||||
|
is_same_toast_filenode
|
||||||
|
------------------------
|
||||||
|
f
|
||||||
|
(1 row)
|
||||||
|
|
||||||
-- SKIP_DATABASE_STATS option
|
-- SKIP_DATABASE_STATS option
|
||||||
VACUUM (SKIP_DATABASE_STATS) vactst;
|
VACUUM (SKIP_DATABASE_STATS) vactst;
|
||||||
-- ONLY_DATABASE_STATS option
|
-- ONLY_DATABASE_STATS option
|
||||||
|
@ -236,7 +236,8 @@ CREATE TABLE vac_option_tab (a INT, t TEXT);
|
|||||||
INSERT INTO vac_option_tab SELECT a, 't' || a FROM generate_series(1, 10) AS a;
|
INSERT INTO vac_option_tab SELECT a, 't' || a FROM generate_series(1, 10) AS a;
|
||||||
ALTER TABLE vac_option_tab ALTER COLUMN t SET STORAGE EXTERNAL;
|
ALTER TABLE vac_option_tab ALTER COLUMN t SET STORAGE EXTERNAL;
|
||||||
-- Check the number of vacuums done on table vac_option_tab and on its
|
-- Check the number of vacuums done on table vac_option_tab and on its
|
||||||
-- toast relation, to check that PROCESS_TOAST works on what it should.
|
-- toast relation, to check that PROCESS_TOAST and PROCESS_MAIN work on
|
||||||
|
-- what they should.
|
||||||
CREATE VIEW vac_option_tab_counts AS
|
CREATE VIEW vac_option_tab_counts AS
|
||||||
SELECT CASE WHEN c.relname IS NULL
|
SELECT CASE WHEN c.relname IS NULL
|
||||||
THEN 'main' ELSE 'toast' END as rel,
|
THEN 'main' ELSE 'toast' END as rel,
|
||||||
@ -251,6 +252,26 @@ VACUUM (PROCESS_TOAST FALSE) vac_option_tab;
|
|||||||
SELECT * FROM vac_option_tab_counts;
|
SELECT * FROM vac_option_tab_counts;
|
||||||
VACUUM (PROCESS_TOAST FALSE, FULL) vac_option_tab; -- error
|
VACUUM (PROCESS_TOAST FALSE, FULL) vac_option_tab; -- error
|
||||||
|
|
||||||
|
-- PROCESS_MAIN option
|
||||||
|
-- Only the toast table is processed.
|
||||||
|
VACUUM (PROCESS_MAIN FALSE) vac_option_tab;
|
||||||
|
SELECT * FROM vac_option_tab_counts;
|
||||||
|
-- Nothing is processed.
|
||||||
|
VACUUM (PROCESS_MAIN FALSE, PROCESS_TOAST FALSE) vac_option_tab;
|
||||||
|
SELECT * FROM vac_option_tab_counts;
|
||||||
|
-- Check if the filenodes nodes have been updated as wanted after FULL.
|
||||||
|
SELECT relfilenode AS main_filenode FROM pg_class
|
||||||
|
WHERE relname = 'vac_option_tab' \gset
|
||||||
|
SELECT t.relfilenode AS toast_filenode FROM pg_class c, pg_class t
|
||||||
|
WHERE c.reltoastrelid = t.oid AND c.relname = 'vac_option_tab' \gset
|
||||||
|
-- Only the toast relation is processed.
|
||||||
|
VACUUM (PROCESS_MAIN FALSE, FULL) vac_option_tab;
|
||||||
|
SELECT relfilenode = :main_filenode AS is_same_main_filenode
|
||||||
|
FROM pg_class WHERE relname = 'vac_option_tab';
|
||||||
|
SELECT t.relfilenode = :toast_filenode AS is_same_toast_filenode
|
||||||
|
FROM pg_class c, pg_class t
|
||||||
|
WHERE c.reltoastrelid = t.oid AND c.relname = 'vac_option_tab';
|
||||||
|
|
||||||
-- SKIP_DATABASE_STATS option
|
-- SKIP_DATABASE_STATS option
|
||||||
VACUUM (SKIP_DATABASE_STATS) vactst;
|
VACUUM (SKIP_DATABASE_STATS) vactst;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user