Add --buffer-usage-limit option to vacuumdb
authorDavid Rowley <[email protected]>
Fri, 7 Apr 2023 00:47:10 +0000 (12:47 +1200)
committerDavid Rowley <[email protected]>
Fri, 7 Apr 2023 00:47:10 +0000 (12:47 +1200)
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/[email protected]

doc/src/sgml/config.sgml
doc/src/sgml/ref/vacuumdb.sgml
src/backend/commands/vacuum.c
src/bin/scripts/vacuumdb.c
src/include/commands/vacuum.h
src/test/regress/expected/vacuum.out

index 992e94400128f86f2df1536676fd35cf72b76902..25111d5caf3bd613ae88010dfe9652476f30f070 100644 (file)
@@ -2015,10 +2015,10 @@ include_dir 'conf.d'
         used by the <command>VACUUM</command> and <command>ANALYZE</command>
         commands.  A setting of <literal>0</literal> will allow the operation
         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
         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
         parameter can be set at any time.  It can be overridden for
         <xref linkend="sql-vacuum"/> and <xref linkend="sql-analyze"/>
index 74bac2d4ba5fae1d1a9efbfa235e6cfff5e7bf62..8280cf0fb07d11f40bc77d85d0dcfd74820f18cd 100644 (file)
@@ -278,6 +278,19 @@ PostgreSQL documentation
       </listitem>
      </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>
       <term><option>-n <replaceable class="parameter">schema</replaceable></option></term>
       <term><option>--schema=<replaceable class="parameter">schema</replaceable></option></term>
index 1980e7664bc879379821c22fbe717c23e64fc6ce..873209d946aef3c9285d826843bf77069c17627a 100644 (file)
@@ -135,7 +135,7 @@ check_vacuum_buffer_usage_limit(int *newval, void **extra,
        return true;
 
    /* 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);
 
    return false;
@@ -225,7 +225,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
            {
                ereport(ERROR,
                        (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)));
            }
 
index 39be265b5bb3956c3d3701630ec345525ae92464..1241644ed5e445f322ced63c2739a11c78d12d2b 100644 (file)
@@ -46,6 +46,7 @@ typedef struct vacuumingOptions
    bool        process_main;
    bool        process_toast;
    bool        skip_database_stats;
+   char       *buffer_usage_limit;
 } vacuumingOptions;
 
 /* object filter options */
@@ -123,6 +124,7 @@ main(int argc, char *argv[])
        {"no-truncate", no_argument, NULL, 10},
        {"no-process-toast", no_argument, NULL, 11},
        {"no-process-main", no_argument, NULL, 12},
+       {"buffer-usage-limit", required_argument, NULL, 13},
        {NULL, 0, NULL, 0}
    };
 
@@ -147,6 +149,7 @@ main(int argc, char *argv[])
    /* initialize options */
    memset(&vacopts, 0, sizeof(vacopts));
    vacopts.parallel_workers = -1;
+   vacopts.buffer_usage_limit = NULL;
    vacopts.no_index_cleanup = false;
    vacopts.force_index_cleanup = false;
    vacopts.do_truncate = true;
@@ -266,6 +269,9 @@ main(int argc, char *argv[])
            case 12:
                vacopts.process_main = false;
                break;
+           case 13:
+               vacopts.buffer_usage_limit = pg_strdup(optarg);
+               break;
            default:
                /* getopt_long already emitted a complaint */
                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",
                 "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 */
    cparams.pghost = host;
    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",
                 "--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 */
    vacopts->skip_database_stats = (PQserverVersion(conn) >= 160000);
 
@@ -1048,6 +1066,13 @@ prepare_vacuum_command(PQExpBuffer sql, int serverVersion,
                                  vacopts->parallel_workers);
                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)
                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(_("  -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(_("      --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(_("      --no-index-cleanup          don't remove index entries that point to dead tuples\n"));
    printf(_("      --no-process-main           skip the main relation\n"));
index 2a856b0e5edc7af3a3c0b5de1c8d651cb403be8a..17e9b4f68e540a558d80e717bc19edfee4b55146 100644 (file)
@@ -213,6 +213,9 @@ typedef enum VacOptValue
  *
  * Note that at least one of VACOPT_VACUUM and VACOPT_ANALYZE must be set
  * in options.
+ *
+ * When adding a new VacuumParam member, consider adding it to vacuumdb as
+ * well.
  */
 typedef struct VacuumParams
 {
index eae274378836b4513477a9ec03fd8a07f0d17e3d..044b761024b3237789fa511ff98e1d4b81a91af4 100644 (file)
@@ -358,10 +358,10 @@ VACUUM (BUFFER_USAGE_LIMIT 0) vac_option_tab;
 ANALYZE (BUFFER_USAGE_LIMIT 0) vac_option_tab;
 -- value exceeds max size error
 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
 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
 VACUUM (BUFFER_USAGE_LIMIT 10000000000) vac_option_tab;
 ERROR:  value: "10000000000": is invalid for buffer_usage_limit