Add --buffer-usage-limit option to vacuumdb

1cbbee033 added BUFFER_USAGE_LIMIT to the VACUUM and ANALYZE commands, so
here we permit that option to be specified in vacuumdb.

In passing, adjust the documents for vacuum_buffer_usage_limit and the
BUFFER_USAGE_LIMIT VACUUM option to mention "kB" rather than "KB".  Do the
same for the ERROR message in ExecVacuum() and
check_vacuum_buffer_usage_limit().  Without that we might tell a user that
the valid minimum value is 128 KB only to reject that because we accept
only "kB" and not "KB".

Also, add a small reminder comment in vacuum.h to try to trigger the
memory of anyone adding new fields to VacuumParams that they might want to
consider if vacuumdb needs to grow a new option too.

Author: Melanie Plageman
Reviewed-by: Justin Pryzby
Reviewed-by: David Rowley
Discussion: https://postgr.es/m/ZAzTg3iEnubscvbf@telsasoft.com
This commit is contained in:
David Rowley 2023-04-07 12:47:10 +12:00
parent 00d1e02be2
commit ae78cae3be
6 changed files with 48 additions and 6 deletions

View File

@ -2015,10 +2015,10 @@ include_dir 'conf.d'
used by the <command>VACUUM</command> and <command>ANALYZE</command> used by the <command>VACUUM</command> and <command>ANALYZE</command>
commands. A setting of <literal>0</literal> will allow the operation commands. A setting of <literal>0</literal> will allow the operation
to use any number of <varname>shared_buffers</varname>. Otherwise to use any number of <varname>shared_buffers</varname>. Otherwise
valid sizes range from <literal>128 KB</literal> to valid sizes range from <literal>128 kB</literal> to
<literal>16 GB</literal>. If the specified size would exceed 1/8 the <literal>16 GB</literal>. If the specified size would exceed 1/8 the
size of <varname>shared_buffers</varname>, the size is silently capped size of <varname>shared_buffers</varname>, the size is silently capped
to that value. The default value is <literal>256 KB</literal>. If to that value. The default value is <literal>256 kB</literal>. If
this value is specified without units, it is taken as kilobytes. This this value is specified without units, it is taken as kilobytes. This
parameter can be set at any time. It can be overridden for parameter can be set at any time. It can be overridden for
<xref linkend="sql-vacuum"/> and <xref linkend="sql-analyze"/> <xref linkend="sql-vacuum"/> and <xref linkend="sql-analyze"/>

View File

@ -278,6 +278,19 @@ PostgreSQL documentation
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>--buffer-usage-limit <replaceable class="parameter">buffer_usage_limit</replaceable></option></term>
<listitem>
<para>
Specifies the
<glossterm linkend="glossary-buffer-access-strategy">Buffer Access Strategy</glossterm>
ring buffer size for a given invocation of <application>vacuumdb</application>.
This size is used to calculate the number of shared buffers which will
be reused as part of this strategy. See <xref linkend="sql-vacuum"/>.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><option>-n <replaceable class="parameter">schema</replaceable></option></term> <term><option>-n <replaceable class="parameter">schema</replaceable></option></term>
<term><option>--schema=<replaceable class="parameter">schema</replaceable></option></term> <term><option>--schema=<replaceable class="parameter">schema</replaceable></option></term>

View File

@ -135,7 +135,7 @@ check_vacuum_buffer_usage_limit(int *newval, void **extra,
return true; return true;
/* Value does not fall within any allowable range */ /* Value does not fall within any allowable range */
GUC_check_errdetail("\"vacuum_buffer_usage_limit\" must be 0 or between %d KB and %d KB", GUC_check_errdetail("\"vacuum_buffer_usage_limit\" must be 0 or between %d kB and %d kB",
MIN_BAS_VAC_RING_SIZE_KB, MAX_BAS_VAC_RING_SIZE_KB); MIN_BAS_VAC_RING_SIZE_KB, MAX_BAS_VAC_RING_SIZE_KB);
return false; return false;
@ -225,7 +225,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
{ {
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE), (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("buffer_usage_limit option must be 0 or between %d KB and %d KB", errmsg("buffer_usage_limit option must be 0 or between %d kB and %d kB",
MIN_BAS_VAC_RING_SIZE_KB, MAX_BAS_VAC_RING_SIZE_KB))); MIN_BAS_VAC_RING_SIZE_KB, MAX_BAS_VAC_RING_SIZE_KB)));
} }

View File

@ -46,6 +46,7 @@ typedef struct vacuumingOptions
bool process_main; bool process_main;
bool process_toast; bool process_toast;
bool skip_database_stats; bool skip_database_stats;
char *buffer_usage_limit;
} vacuumingOptions; } vacuumingOptions;
/* object filter options */ /* object filter options */
@ -123,6 +124,7 @@ main(int argc, char *argv[])
{"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}, {"no-process-main", no_argument, NULL, 12},
{"buffer-usage-limit", required_argument, NULL, 13},
{NULL, 0, NULL, 0} {NULL, 0, NULL, 0}
}; };
@ -147,6 +149,7 @@ main(int argc, char *argv[])
/* initialize options */ /* initialize options */
memset(&vacopts, 0, sizeof(vacopts)); memset(&vacopts, 0, sizeof(vacopts));
vacopts.parallel_workers = -1; vacopts.parallel_workers = -1;
vacopts.buffer_usage_limit = NULL;
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;
@ -266,6 +269,9 @@ main(int argc, char *argv[])
case 12: case 12:
vacopts.process_main = false; vacopts.process_main = false;
break; break;
case 13:
vacopts.buffer_usage_limit = pg_strdup(optarg);
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);
@ -343,6 +349,14 @@ main(int argc, char *argv[])
pg_fatal("cannot use the \"%s\" option with the \"%s\" option", pg_fatal("cannot use the \"%s\" option with the \"%s\" option",
"no-index-cleanup", "force-index-cleanup"); "no-index-cleanup", "force-index-cleanup");
/*
* buffer-usage-limit is not allowed with VACUUM FULL unless ANALYZE is
* included too.
*/
if (vacopts.buffer_usage_limit && vacopts.full && !vacopts.and_analyze)
pg_fatal("cannot use the \"%s\" option with the \"%s\" option",
"buffer-usage-limit", "full");
/* fill cparams except for dbname, which is set below */ /* fill cparams except for dbname, which is set below */
cparams.pghost = host; cparams.pghost = host;
cparams.pgport = port; cparams.pgport = port;
@ -550,6 +564,10 @@ vacuum_one_database(ConnParams *cparams,
pg_fatal("cannot use the \"%s\" option on server versions older than PostgreSQL %s", pg_fatal("cannot use the \"%s\" option on server versions older than PostgreSQL %s",
"--parallel", "13"); "--parallel", "13");
if (vacopts->buffer_usage_limit && PQserverVersion(conn) < 160000)
pg_fatal("cannot use the \"%s\" option on server versions older than PostgreSQL %s",
"--buffer-usage-limit", "16");
/* skip_database_stats is used automatically if server supports it */ /* skip_database_stats is used automatically if server supports it */
vacopts->skip_database_stats = (PQserverVersion(conn) >= 160000); vacopts->skip_database_stats = (PQserverVersion(conn) >= 160000);
@ -1048,6 +1066,13 @@ prepare_vacuum_command(PQExpBuffer sql, int serverVersion,
vacopts->parallel_workers); vacopts->parallel_workers);
sep = comma; sep = comma;
} }
if (vacopts->buffer_usage_limit)
{
Assert(serverVersion >= 160000);
appendPQExpBuffer(sql, "%sBUFFER_USAGE_LIMIT '%s'", sep,
vacopts->buffer_usage_limit);
sep = comma;
}
if (sep != paren) if (sep != paren)
appendPQExpBufferChar(sql, ')'); appendPQExpBufferChar(sql, ')');
} }
@ -1111,6 +1136,7 @@ help(const char *progname)
printf(_(" --force-index-cleanup always remove index entries that point to dead tuples\n")); printf(_(" --force-index-cleanup always remove index entries that point to dead tuples\n"));
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(_(" --buffer-usage-limit=BUFSIZE size of ring buffer used for 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-main skip the main relation\n"));

View File

@ -213,6 +213,9 @@ typedef enum VacOptValue
* *
* Note that at least one of VACOPT_VACUUM and VACOPT_ANALYZE must be set * Note that at least one of VACOPT_VACUUM and VACOPT_ANALYZE must be set
* in options. * in options.
*
* When adding a new VacuumParam member, consider adding it to vacuumdb as
* well.
*/ */
typedef struct VacuumParams typedef struct VacuumParams
{ {

View File

@ -358,10 +358,10 @@ VACUUM (BUFFER_USAGE_LIMIT 0) vac_option_tab;
ANALYZE (BUFFER_USAGE_LIMIT 0) vac_option_tab; ANALYZE (BUFFER_USAGE_LIMIT 0) vac_option_tab;
-- value exceeds max size error -- value exceeds max size error
VACUUM (BUFFER_USAGE_LIMIT 16777220) vac_option_tab; VACUUM (BUFFER_USAGE_LIMIT 16777220) vac_option_tab;
ERROR: buffer_usage_limit option must be 0 or between 128 KB and 16777216 KB ERROR: buffer_usage_limit option must be 0 or between 128 kB and 16777216 kB
-- value is less than min size error -- value is less than min size error
VACUUM (BUFFER_USAGE_LIMIT 120) vac_option_tab; VACUUM (BUFFER_USAGE_LIMIT 120) vac_option_tab;
ERROR: buffer_usage_limit option must be 0 or between 128 KB and 16777216 KB ERROR: buffer_usage_limit option must be 0 or between 128 kB and 16777216 kB
-- integer overflow error -- integer overflow error
VACUUM (BUFFER_USAGE_LIMIT 10000000000) vac_option_tab; VACUUM (BUFFER_USAGE_LIMIT 10000000000) vac_option_tab;
ERROR: value: "10000000000": is invalid for buffer_usage_limit ERROR: value: "10000000000": is invalid for buffer_usage_limit