mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
Add --parallel option to vacuumdb command.
Commit 40d964ec99
allowed vacuum command to leverage multiple CPUs by
invoking parallel workers to process indexes. This commit provides a
'--parallel' option to specify the parallel degree used by vacuum command.
Author: Masahiko Sawada, with few modifications by me
Reviewed-by: Mahendra Singh and Amit Kapila
Discussion: https://postgr.es/m/CAD21AoDTPMgzSkV4E3SFo1CH_x50bf5PqZFQf4jmqjk-C03BWg@mail.gmail.com
This commit is contained in:
@ -226,6 +226,24 @@ PostgreSQL documentation
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-P <replaceable class="parameter">parallel_degree</replaceable></option></term>
|
||||||
|
<term><option>--parallel=<replaceable class="parameter">parallel_degree</replaceable></option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Specify the parallel degree of <firstterm>parallel vacuum</firstterm>.
|
||||||
|
This allows the vacuum to leverage multiple CPUs to process indexes.
|
||||||
|
See <xref linkend="sql-vacuum"/>.
|
||||||
|
</para>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
This option is only available for servers running
|
||||||
|
<productname>PostgreSQL</productname> 13 and later.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>-q</option></term>
|
<term><option>-q</option></term>
|
||||||
<term><option>--quiet</option></term>
|
<term><option>--quiet</option></term>
|
||||||
|
@ -3,7 +3,7 @@ use warnings;
|
|||||||
|
|
||||||
use PostgresNode;
|
use PostgresNode;
|
||||||
use TestLib;
|
use TestLib;
|
||||||
use Test::More tests => 44;
|
use Test::More tests => 49;
|
||||||
|
|
||||||
program_help_ok('vacuumdb');
|
program_help_ok('vacuumdb');
|
||||||
program_version_ok('vacuumdb');
|
program_version_ok('vacuumdb');
|
||||||
@ -48,6 +48,14 @@ $node->issues_sql_like(
|
|||||||
$node->command_fails(
|
$node->command_fails(
|
||||||
[ 'vacuumdb', '--analyze-only', '--disable-page-skipping', 'postgres' ],
|
[ 'vacuumdb', '--analyze-only', '--disable-page-skipping', 'postgres' ],
|
||||||
'--analyze-only and --disable-page-skipping specified together');
|
'--analyze-only and --disable-page-skipping specified together');
|
||||||
|
$node->issues_sql_like(
|
||||||
|
[ 'vacuumdb', '-P', 2, 'postgres' ],
|
||||||
|
qr/statement: VACUUM \(PARALLEL 2\).*;/,
|
||||||
|
'vacuumdb -P 2');
|
||||||
|
$node->issues_sql_like(
|
||||||
|
[ 'vacuumdb', '-P', 0, 'postgres' ],
|
||||||
|
qr/statement: VACUUM \(PARALLEL 0\).*;/,
|
||||||
|
'vacuumdb -P 0');
|
||||||
$node->command_ok([qw(vacuumdb -Z --table=pg_am dbname=template1)],
|
$node->command_ok([qw(vacuumdb -Z --table=pg_am dbname=template1)],
|
||||||
'vacuumdb with connection string');
|
'vacuumdb with connection string');
|
||||||
|
|
||||||
@ -81,6 +89,9 @@ $node->command_fails(
|
|||||||
$node->command_fails(
|
$node->command_fails(
|
||||||
[ 'vacuumdb', '--analyze', '--table', 'vactable(c)', 'postgres' ],
|
[ 'vacuumdb', '--analyze', '--table', 'vactable(c)', 'postgres' ],
|
||||||
'incorrect column name with ANALYZE');
|
'incorrect column name with ANALYZE');
|
||||||
|
$node->command_fails(
|
||||||
|
[ 'vacuumdb', '-P', -1, 'postgres' ],
|
||||||
|
'negative parallel degree');
|
||||||
$node->issues_sql_like(
|
$node->issues_sql_like(
|
||||||
[ 'vacuumdb', '--analyze', '--table', 'vactable(a, b)', 'postgres' ],
|
[ 'vacuumdb', '--analyze', '--table', 'vactable(a, b)', 'postgres' ],
|
||||||
qr/statement: VACUUM \(ANALYZE\) public.vactable\(a, b\);/,
|
qr/statement: VACUUM \(ANALYZE\) public.vactable\(a, b\);/,
|
||||||
|
@ -35,6 +35,8 @@ typedef struct vacuumingOptions
|
|||||||
bool skip_locked;
|
bool skip_locked;
|
||||||
int min_xid_age;
|
int min_xid_age;
|
||||||
int min_mxid_age;
|
int min_mxid_age;
|
||||||
|
int parallel_workers; /* >= 0 indicates user specified the
|
||||||
|
* parallel degree, otherwise -1 */
|
||||||
} vacuumingOptions;
|
} vacuumingOptions;
|
||||||
|
|
||||||
|
|
||||||
@ -87,6 +89,7 @@ main(int argc, char *argv[])
|
|||||||
{"full", no_argument, NULL, 'f'},
|
{"full", no_argument, NULL, 'f'},
|
||||||
{"verbose", no_argument, NULL, 'v'},
|
{"verbose", no_argument, NULL, 'v'},
|
||||||
{"jobs", required_argument, NULL, 'j'},
|
{"jobs", required_argument, NULL, 'j'},
|
||||||
|
{"parallel", required_argument, NULL, 'P'},
|
||||||
{"maintenance-db", required_argument, NULL, 2},
|
{"maintenance-db", required_argument, NULL, 2},
|
||||||
{"analyze-in-stages", no_argument, NULL, 3},
|
{"analyze-in-stages", no_argument, NULL, 3},
|
||||||
{"disable-page-skipping", no_argument, NULL, 4},
|
{"disable-page-skipping", no_argument, NULL, 4},
|
||||||
@ -116,6 +119,7 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
/* initialize options to all false */
|
/* initialize options to all false */
|
||||||
memset(&vacopts, 0, sizeof(vacopts));
|
memset(&vacopts, 0, sizeof(vacopts));
|
||||||
|
vacopts.parallel_workers = -1;
|
||||||
|
|
||||||
pg_logging_init(argv[0]);
|
pg_logging_init(argv[0]);
|
||||||
progname = get_progname(argv[0]);
|
progname = get_progname(argv[0]);
|
||||||
@ -123,7 +127,7 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
handle_help_version_opts(argc, argv, "vacuumdb", help);
|
handle_help_version_opts(argc, argv, "vacuumdb", help);
|
||||||
|
|
||||||
while ((c = getopt_long(argc, argv, "h:p:U:wWeqd:zZFat:fvj:", long_options, &optindex)) != -1)
|
while ((c = getopt_long(argc, argv, "h:p:U:wWeqd:zZFat:fvj:P:", long_options, &optindex)) != -1)
|
||||||
{
|
{
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
@ -183,6 +187,14 @@ main(int argc, char *argv[])
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'P':
|
||||||
|
vacopts.parallel_workers = atoi(optarg);
|
||||||
|
if (vacopts.parallel_workers < 0)
|
||||||
|
{
|
||||||
|
pg_log_error("parallel vacuum degree must be a non-negative integer");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
maintenance_db = pg_strdup(optarg);
|
maintenance_db = pg_strdup(optarg);
|
||||||
break;
|
break;
|
||||||
@ -258,6 +270,23 @@ main(int argc, char *argv[])
|
|||||||
/* allow 'and_analyze' with 'analyze_only' */
|
/* allow 'and_analyze' with 'analyze_only' */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Prohibit full and analyze_only options with parallel option */
|
||||||
|
if (vacopts.parallel_workers >= 0)
|
||||||
|
{
|
||||||
|
if (vacopts.analyze_only)
|
||||||
|
{
|
||||||
|
pg_log_error("cannot use the \"%s\" option when performing only analyze",
|
||||||
|
"parallel");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (vacopts.full)
|
||||||
|
{
|
||||||
|
pg_log_error("cannot use the \"%s\" option when performing full",
|
||||||
|
"parallel");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setup_cancel_handler(NULL);
|
setup_cancel_handler(NULL);
|
||||||
|
|
||||||
/* Avoid opening extra connections. */
|
/* Avoid opening extra connections. */
|
||||||
@ -405,6 +434,13 @@ vacuum_one_database(const char *dbname, vacuumingOptions *vacopts,
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vacopts->parallel_workers >= 0 && PQserverVersion(conn) < 130000)
|
||||||
|
{
|
||||||
|
pg_log_error("cannot use the \"%s\" option on server versions older than PostgreSQL %s",
|
||||||
|
"--parallel", "13");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
{
|
{
|
||||||
if (stage != ANALYZE_NO_STAGE)
|
if (stage != ANALYZE_NO_STAGE)
|
||||||
@ -823,6 +859,14 @@ prepare_vacuum_command(PQExpBuffer sql, int serverVersion,
|
|||||||
appendPQExpBuffer(sql, "%sANALYZE", sep);
|
appendPQExpBuffer(sql, "%sANALYZE", sep);
|
||||||
sep = comma;
|
sep = comma;
|
||||||
}
|
}
|
||||||
|
if (vacopts->parallel_workers >= 0)
|
||||||
|
{
|
||||||
|
/* PARALLEL is supported since v13 */
|
||||||
|
Assert(serverVersion >= 130000);
|
||||||
|
appendPQExpBuffer(sql, "%sPARALLEL %d", sep,
|
||||||
|
vacopts->parallel_workers);
|
||||||
|
sep = comma;
|
||||||
|
}
|
||||||
if (sep != paren)
|
if (sep != paren)
|
||||||
appendPQExpBufferChar(sql, ')');
|
appendPQExpBufferChar(sql, ')');
|
||||||
}
|
}
|
||||||
@ -886,6 +930,7 @@ help(const char *progname)
|
|||||||
printf(_(" -j, --jobs=NUM use this many concurrent connections to vacuum\n"));
|
printf(_(" -j, --jobs=NUM use this many concurrent connections to vacuum\n"));
|
||||||
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(_(" -P, --parallel=PARALLEL_DEGREE use this many background workers for vacuum, if available\n"));
|
||||||
printf(_(" -q, --quiet don't write any messages\n"));
|
printf(_(" -q, --quiet don't write any messages\n"));
|
||||||
printf(_(" --skip-locked skip relations that cannot be immediately locked\n"));
|
printf(_(" --skip-locked skip relations that cannot be immediately locked\n"));
|
||||||
printf(_(" -t, --table='TABLE[(COLUMNS)]' vacuum specific table(s) only\n"));
|
printf(_(" -t, --table='TABLE[(COLUMNS)]' vacuum specific table(s) only\n"));
|
||||||
|
Reference in New Issue
Block a user