Fix the usage of parallel and full options of vacuum command.

Earlier we were inconsistent in allowing the usage of parallel and
full options.  Change it such that we disallow them only when they are
combined in a way that we don't support.

In passing, improve the comments in some of the existing tests of parallel
vacuum.

Reported-by: Tushar Ahuja
Author: Justin Pryzby, Amit Kapila
Reviewed-by: Sawada Masahiko, Michael Paquier, Mahendra Singh Thalor and
Amit Kapila
Discussion: https://postgr.es/m/58c8d171-e665-6fa3-a9d3-d9423b694dae%40enterprisedb.com
This commit is contained in:
Amit Kapila 2020-04-16 10:44:03 +05:30
parent 542d7817f7
commit 24d2d38b1e
4 changed files with 26 additions and 23 deletions

View File

@ -235,22 +235,22 @@ VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ ANALYZE ] [ <replaceable class="paramet
Perform index vacuum and index cleanup phases of <command>VACUUM</command> Perform index vacuum and index cleanup phases of <command>VACUUM</command>
in parallel using <replaceable class="parameter">integer</replaceable> in parallel using <replaceable class="parameter">integer</replaceable>
background workers (for the details of each vacuum phase, please background workers (for the details of each vacuum phase, please
refer to <xref linkend="vacuum-phases"/>). If the refer to <xref linkend="vacuum-phases"/>). In plain <command>VACUUM</command>
<literal>PARALLEL</literal> option is omitted, then the number of workers (without <literal>FULL</literal>), if the <literal>PARALLEL</literal> option
is determined based on the number of indexes that support parallel vacuum is omitted, then the number of workers is determined based on the number of
operation on the relation, and is further limited by <xref indexes on the relation that support parallel vacuum operation and is further
linkend="guc-max-parallel-workers-maintenance"/>. limited by <xref linkend="guc-max-parallel-workers-maintenance"/>. An index
An index can participate in parallel vacuum if and only if the size can participate in parallel vacuum if and only if the size of the index is
of the index is more than <xref linkend="guc-min-parallel-index-scan-size"/>. more than <xref linkend="guc-min-parallel-index-scan-size"/>. Please note
Please note that it is not guaranteed that the number of parallel workers that it is not guaranteed that the number of parallel workers specified in
specified in <replaceable class="parameter">integer</replaceable> will <replaceable class="parameter">integer</replaceable> will be used during
be used during execution. It is possible for a vacuum to run with fewer execution. It is possible for a vacuum to run with fewer workers than
workers than specified, or even with no workers at all. Only one worker specified, or even with no workers at all. Only one worker can be used per
can be used per index. So parallel workers are launched only when there index. So parallel workers are launched only when there are at least
are at least <literal>2</literal> indexes in the table. Workers for <literal>2</literal> indexes in the table. Workers for vacuum are launched
vacuum are launched before the start of each phase and exit at the end of before the start of each phase and exit at the end of the phase. These
the phase. These behaviors might change in a future release. This behaviors might change in a future release. This option can't be used with
option can't be used with the <literal>FULL</literal> option. the <literal>FULL</literal> option.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>

View File

@ -104,7 +104,6 @@ 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 parallel_option = false;
ListCell *lc; ListCell *lc;
/* Set default value */ /* Set default value */
@ -145,7 +144,6 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
params.truncate = get_vacopt_ternary_value(opt); params.truncate = get_vacopt_ternary_value(opt);
else if (strcmp(opt->defname, "parallel") == 0) else if (strcmp(opt->defname, "parallel") == 0)
{ {
parallel_option = true;
if (opt->arg == NULL) if (opt->arg == NULL)
{ {
ereport(ERROR, ereport(ERROR,
@ -199,10 +197,10 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
!(params.options & (VACOPT_FULL | VACOPT_FREEZE))); !(params.options & (VACOPT_FULL | VACOPT_FREEZE)));
Assert(!(params.options & VACOPT_SKIPTOAST)); Assert(!(params.options & VACOPT_SKIPTOAST));
if ((params.options & VACOPT_FULL) && parallel_option) if ((params.options & VACOPT_FULL) && params.nworkers > 0)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot specify both FULL and PARALLEL options"))); errmsg("VACUUM FULL cannot be performed in parallel")));
/* /*
* Make sure VACOPT_ANALYZE is specified if any column lists are present. * Make sure VACOPT_ANALYZE is specified if any column lists are present.

View File

@ -115,15 +115,17 @@ LINE 1: VACUUM (PARALLEL -1) pvactst;
^ ^
VACUUM (PARALLEL 2, INDEX_CLEANUP FALSE) pvactst; VACUUM (PARALLEL 2, INDEX_CLEANUP FALSE) pvactst;
VACUUM (PARALLEL 2, FULL TRUE) pvactst; -- error, cannot use both PARALLEL and FULL VACUUM (PARALLEL 2, FULL TRUE) pvactst; -- error, cannot use both PARALLEL and FULL
ERROR: cannot specify both FULL and PARALLEL options ERROR: VACUUM FULL cannot be performed in parallel
VACUUM (PARALLEL) pvactst; -- error, cannot use PARALLEL option without parallel degree VACUUM (PARALLEL) pvactst; -- error, cannot use PARALLEL option without parallel degree
ERROR: parallel option requires a value between 0 and 1024 ERROR: parallel option requires a value between 0 and 1024
LINE 1: VACUUM (PARALLEL) pvactst; LINE 1: VACUUM (PARALLEL) pvactst;
^ ^
-- Test different combinations of parallel and full options for temporary tables
CREATE TEMPORARY TABLE tmp (a int PRIMARY KEY); CREATE TEMPORARY TABLE tmp (a int PRIMARY KEY);
CREATE INDEX tmp_idx1 ON tmp (a); CREATE INDEX tmp_idx1 ON tmp (a);
VACUUM (PARALLEL 1) tmp; -- disables parallel vacuum option VACUUM (PARALLEL 1, FULL FALSE) tmp; -- parallel vacuum disabled for temp tables
WARNING: disabling parallel option of vacuum on "tmp" --- cannot vacuum temporary tables in parallel WARNING: disabling parallel option of vacuum on "tmp" --- cannot vacuum temporary tables in parallel
VACUUM (PARALLEL 0, FULL TRUE) tmp; -- can specify parallel disabled (even though that's implied by FULL)
RESET min_parallel_index_scan_size; RESET min_parallel_index_scan_size;
DROP TABLE pvactst; DROP TABLE pvactst;
-- INDEX_CLEANUP option -- INDEX_CLEANUP option

View File

@ -100,9 +100,12 @@ VACUUM (PARALLEL -1) pvactst; -- error
VACUUM (PARALLEL 2, INDEX_CLEANUP FALSE) pvactst; VACUUM (PARALLEL 2, INDEX_CLEANUP FALSE) pvactst;
VACUUM (PARALLEL 2, FULL TRUE) pvactst; -- error, cannot use both PARALLEL and FULL VACUUM (PARALLEL 2, FULL TRUE) pvactst; -- error, cannot use both PARALLEL and FULL
VACUUM (PARALLEL) pvactst; -- error, cannot use PARALLEL option without parallel degree VACUUM (PARALLEL) pvactst; -- error, cannot use PARALLEL option without parallel degree
-- Test different combinations of parallel and full options for temporary tables
CREATE TEMPORARY TABLE tmp (a int PRIMARY KEY); CREATE TEMPORARY TABLE tmp (a int PRIMARY KEY);
CREATE INDEX tmp_idx1 ON tmp (a); CREATE INDEX tmp_idx1 ON tmp (a);
VACUUM (PARALLEL 1) tmp; -- disables parallel vacuum option VACUUM (PARALLEL 1, FULL FALSE) tmp; -- parallel vacuum disabled for temp tables
VACUUM (PARALLEL 0, FULL TRUE) tmp; -- can specify parallel disabled (even though that's implied by FULL)
RESET min_parallel_index_scan_size; RESET min_parallel_index_scan_size;
DROP TABLE pvactst; DROP TABLE pvactst;