I've attached a new patch to show roughly what I think this new GUC should
look like.  I'm hoping this sparks more discussion, if nothing else.

On Tue, Jun 18, 2024 at 12:36:42PM +0200, Frédéric Yhuel wrote:
> By the way, I wonder if there were any off-list discussions after Robert's
> conference at PGConf.dev (and I'm waiting for the video of the conf).

I don't recall any discussions about this idea, but Robert did briefly
mention it in his talk [0].

[0] https://www.youtube.com/watch?v=RfTD-Twpvac

-- 
nathan
>From ccfaee370835d755b663357bf139fea729a5f454 Mon Sep 17 00:00:00 2001
From: Nathan Bossart <nat...@postgresql.org>
Date: Wed, 7 Aug 2024 16:22:37 -0500
Subject: [PATCH v2 1/1] autovacuum_max_threshold

---
 doc/src/sgml/config.sgml                      | 24 +++++++++++++++++++
 doc/src/sgml/ref/create_table.sgml            | 15 ++++++++++++
 src/backend/access/common/reloptions.c        | 11 +++++++++
 src/backend/postmaster/autovacuum.c           | 11 +++++++++
 src/backend/utils/misc/guc_tables.c           |  9 +++++++
 src/backend/utils/misc/postgresql.conf.sample |  2 ++
 src/bin/psql/tab-complete.c                   |  2 ++
 src/include/postmaster/autovacuum.h           |  1 +
 src/include/utils/rel.h                       |  1 +
 9 files changed, 76 insertions(+)

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index a1a1d58a43..10855b0e19 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -8615,6 +8615,30 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH 
csv;
       </listitem>
      </varlistentry>
 
+     <varlistentry id="guc-autovacuum-max-threshold" 
xreflabel="autovacuum_max_threshold">
+      <term><varname>autovacuum_max_threshold</varname> (<type>integer</type>)
+      <indexterm>
+       <primary><varname>autovacuum_max_threshold</varname></primary>
+       <secondary>configuration parameter</secondary>
+      </indexterm>
+      </term>
+      <listitem>
+       <para>
+        Specifies the maximum number of updated or deleted tuples needed to
+        trigger a <command>VACUUM</command> in any one table, i.e., a cap on
+        the value calculated with
+        <varname>autovacuum_vacuum_threshold</varname> and
+        <varname>autovacuum_vacuum_scale_factor</varname>.  The default is
+        100,000,000 tuples.  If -1 is specified, autovacuum will not enforce a
+        maximum number of updated or deleted tuples that will trigger a
+        <command>VACUUM</command> operation.  This parameter can only be set in
+        the <filename>postgresql.conf</filename> file or on the server command
+        line; but the setting can be overridden for individual tables by
+        changing storage parameters.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry id="guc-autovacuum-vacuum-insert-threshold" 
xreflabel="autovacuum_vacuum_insert_threshold">
       <term><varname>autovacuum_vacuum_insert_threshold</varname> 
(<type>integer</type>)
       <indexterm>
diff --git a/doc/src/sgml/ref/create_table.sgml 
b/doc/src/sgml/ref/create_table.sgml
index 93b3f664f2..19b5ea7421 100644
--- a/doc/src/sgml/ref/create_table.sgml
+++ b/doc/src/sgml/ref/create_table.sgml
@@ -1596,6 +1596,21 @@ WITH ( MODULUS <replaceable 
class="parameter">numeric_literal</replaceable>, REM
     </listitem>
    </varlistentry>
 
+   <varlistentry id="reloption-autovacuum-max-threshold" 
xreflabel="autovacuum_max_threshold">
+    <term><literal>autovacuum_max_threshold</literal>, 
<literal>toast.autovacuum_max_threshold</literal> (<type>integer</type>)
+    <indexterm>
+     <primary><varname>autovacuum_max_threshold</varname></primary>
+     <secondary>storage parameter</secondary>
+    </indexterm>
+    </term>
+   <listitem>
+    <para>
+     Per-table value for <xref linkend="guc-autovacuum-max-threshold"/>
+     parameter.
+    </para>
+   </listitem>
+  </varlistentry>
+
    <varlistentry id="reloption-autovacuum-vacuum-scale-factor" 
xreflabel="autovacuum_vacuum_scale_factor">
     <term><literal>autovacuum_vacuum_scale_factor</literal>, 
<literal>toast.autovacuum_vacuum_scale_factor</literal> (<type>floating 
point</type>)
     <indexterm>
diff --git a/src/backend/access/common/reloptions.c 
b/src/backend/access/common/reloptions.c
index 49fd35bfc5..c18ee4c497 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -231,6 +231,15 @@ static relopt_int intRelOpts[] =
                },
                -1, 0, INT_MAX
        },
+       {
+               {
+                       "autovacuum_max_threshold",
+                       "Maximum number of tuple updates or deletes prior to 
vacuum",
+                       RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
+                       ShareUpdateExclusiveLock
+               },
+               -1, 0, INT_MAX
+       },
        {
                {
                        "autovacuum_vacuum_insert_threshold",
@@ -1843,6 +1852,8 @@ default_reloptions(Datum reloptions, bool validate, 
relopt_kind kind)
                offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, 
enabled)},
                {"autovacuum_vacuum_threshold", RELOPT_TYPE_INT,
                offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, 
vacuum_threshold)},
+               {"autovacuum_max_threshold", RELOPT_TYPE_INT,
+               offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, 
vacuum_max_threshold)},
                {"autovacuum_vacuum_insert_threshold", RELOPT_TYPE_INT,
                offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, 
vacuum_ins_threshold)},
                {"autovacuum_analyze_threshold", RELOPT_TYPE_INT,
diff --git a/src/backend/postmaster/autovacuum.c 
b/src/backend/postmaster/autovacuum.c
index 4e4a0ccbef..d43d48abc8 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -119,6 +119,7 @@ int                 autovacuum_max_workers;
 int                    autovacuum_work_mem = -1;
 int                    autovacuum_naptime;
 int                    autovacuum_vac_thresh;
+int                    autovacuum_max_thresh;
 double         autovacuum_vac_scale;
 int                    autovacuum_vac_ins_thresh;
 double         autovacuum_vac_ins_scale;
@@ -2887,6 +2888,8 @@ recheck_relation_needs_vacanalyze(Oid relid,
  * threshold.  This threshold is calculated as
  *
  * threshold = vac_base_thresh + vac_scale_factor * reltuples
+ * if (threshold > vac_max_thresh)
+ *     threshold = vac_max_thres;
  *
  * For analyze, the analysis done is that the number of tuples inserted,
  * deleted and updated since the last analyze exceeds a threshold calculated
@@ -2925,6 +2928,7 @@ relation_needs_vacanalyze(Oid relid,
 
        /* constants from reloptions or GUC variables */
        int                     vac_base_thresh,
+                               vac_max_thresh,
                                vac_ins_base_thresh,
                                anl_base_thresh;
        float4          vac_scale_factor,
@@ -2966,6 +2970,10 @@ relation_needs_vacanalyze(Oid relid,
                ? relopts->vacuum_threshold
                : autovacuum_vac_thresh;
 
+       vac_max_thresh = (relopts && relopts->vacuum_max_threshold >= 0)
+               ? relopts->vacuum_max_threshold
+               : autovacuum_max_thresh;
+
        vac_ins_scale_factor = (relopts && relopts->vacuum_ins_scale_factor >= 
0)
                ? relopts->vacuum_ins_scale_factor
                : autovacuum_vac_ins_scale;
@@ -3039,6 +3047,9 @@ relation_needs_vacanalyze(Oid relid,
                        reltuples = 0;
 
                vacthresh = (float4) vac_base_thresh + vac_scale_factor * 
reltuples;
+               if (vac_max_thresh >= 0 && vacthresh > (float4) vac_max_thresh)
+                       vacthresh = (float4) vac_max_thresh;
+
                vacinsthresh = (float4) vac_ins_base_thresh + 
vac_ins_scale_factor * reltuples;
                anlthresh = (float4) anl_base_thresh + anl_scale_factor * 
reltuples;
 
diff --git a/src/backend/utils/misc/guc_tables.c 
b/src/backend/utils/misc/guc_tables.c
index c0a52cdcc3..9aae183786 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -3403,6 +3403,15 @@ struct config_int ConfigureNamesInt[] =
                50, 0, INT_MAX,
                NULL, NULL, NULL
        },
+       {
+               {"autovacuum_max_threshold", PGC_SIGHUP, AUTOVACUUM,
+                       gettext_noop("Maximum number of tuple updates or 
deletes prior to vacuum."),
+                       NULL
+               },
+               &autovacuum_max_thresh,
+               100000000, -1, INT_MAX,
+               NULL, NULL, NULL
+       },
        {
                {"autovacuum_vacuum_insert_threshold", PGC_SIGHUP, AUTOVACUUM,
                        gettext_noop("Minimum number of tuple inserts prior to 
vacuum, or -1 to disable insert vacuums."),
diff --git a/src/backend/utils/misc/postgresql.conf.sample 
b/src/backend/utils/misc/postgresql.conf.sample
index 9ec9f97e92..e7cec694f3 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -663,6 +663,8 @@
 #autovacuum_naptime = 1min             # time between autovacuum runs
 #autovacuum_vacuum_threshold = 50      # min number of row updates before
                                        # vacuum
+#autovacuum_max_threshold = 100000000  # max number of row updates before
+                                       # vacuum
 #autovacuum_vacuum_insert_threshold = 1000     # min number of row inserts
                                                # before vacuum; -1 disables 
insert
                                                # vacuums
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 024469474d..f3ce76e23d 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -1295,6 +1295,7 @@ static const char *const table_storage_parameters[] = {
        "autovacuum_freeze_max_age",
        "autovacuum_freeze_min_age",
        "autovacuum_freeze_table_age",
+       "autovacuum_max_threshold",
        "autovacuum_multixact_freeze_max_age",
        "autovacuum_multixact_freeze_min_age",
        "autovacuum_multixact_freeze_table_age",
@@ -1311,6 +1312,7 @@ static const char *const table_storage_parameters[] = {
        "toast.autovacuum_freeze_max_age",
        "toast.autovacuum_freeze_min_age",
        "toast.autovacuum_freeze_table_age",
+       "toast.autovacuum_max_threshold",
        "toast.autovacuum_multixact_freeze_max_age",
        "toast.autovacuum_multixact_freeze_min_age",
        "toast.autovacuum_multixact_freeze_table_age",
diff --git a/src/include/postmaster/autovacuum.h 
b/src/include/postmaster/autovacuum.h
index cae1e8b329..efbab7bfa9 100644
--- a/src/include/postmaster/autovacuum.h
+++ b/src/include/postmaster/autovacuum.h
@@ -32,6 +32,7 @@ extern PGDLLIMPORT int autovacuum_max_workers;
 extern PGDLLIMPORT int autovacuum_work_mem;
 extern PGDLLIMPORT int autovacuum_naptime;
 extern PGDLLIMPORT int autovacuum_vac_thresh;
+extern PGDLLIMPORT int autovacuum_max_thresh;
 extern PGDLLIMPORT double autovacuum_vac_scale;
 extern PGDLLIMPORT int autovacuum_vac_ins_thresh;
 extern PGDLLIMPORT double autovacuum_vac_ins_scale;
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index 8700204953..bcc6e2607b 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -309,6 +309,7 @@ typedef struct AutoVacOpts
 {
        bool            enabled;
        int                     vacuum_threshold;
+       int                     vacuum_max_threshold;
        int                     vacuum_ins_threshold;
        int                     analyze_threshold;
        int                     vacuum_cost_limit;
-- 
2.39.3 (Apple Git-146)

Reply via email to