]> granicus.if.org Git - postgresql/commitdiff
Update autovacuum to use reloptions instead of a system catalog, for
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Mon, 9 Feb 2009 20:57:59 +0000 (20:57 +0000)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Mon, 9 Feb 2009 20:57:59 +0000 (20:57 +0000)
per-table overrides of parameters.

This removes a whole class of problems related to misusing the catalog,
and perhaps more importantly, gives us pg_dump support for the parameters.

Based on a patch by Euler Taveira de Oliveira, heavily reworked by me.

13 files changed:
doc/src/sgml/catalogs.sgml
doc/src/sgml/config.sgml
doc/src/sgml/maintenance.sgml
doc/src/sgml/ref/alter_table.sgml
doc/src/sgml/ref/create_table.sgml
src/backend/access/common/reloptions.c
src/backend/catalog/Makefile
src/backend/postmaster/autovacuum.c
src/include/catalog/catversion.h
src/include/catalog/indexing.h
src/include/catalog/pg_autovacuum.h [deleted file]
src/include/utils/rel.h
src/test/regress/expected/sanity_check.out

index bcbf866fc86fba591646b36955c073d1937ba8c2..bc1a826d38c48256db6ba29c957805ac471690db 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.196 2009/02/07 19:27:25 momjian Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.197 2009/02/09 20:57:59 alvherre Exp $ -->
 <!--
  Documentation of the system catalogs, directed toward PostgreSQL developers
  -->
       <entry>authorization identifier membership relationships</entry>
      </row>
 
-     <row>
-      <entry><link linkend="catalog-pg-autovacuum"><structname>pg_autovacuum</structname></link></entry>
-      <entry>per-relation autovacuum configuration parameters</entry>
-     </row>
-
      <row>
       <entry><link linkend="catalog-pg-cast"><structname>pg_cast</structname></link></entry>
       <entry>casts (data type conversions)</entry>
  </sect1>
 
 
- <sect1 id="catalog-pg-autovacuum">
-  <title><structname>pg_autovacuum</structname></title>
-
-  <indexterm zone="catalog-pg-autovacuum">
-   <primary>pg_autovacuum</primary>
-  </indexterm>
-
-  <indexterm zone="catalog-pg-autovacuum">
-   <primary>autovacuum</primary>
-   <secondary>table-specific configuration</secondary>
-  </indexterm>
-
-  <para>
-   The catalog <structname>pg_autovacuum</structname> stores optional
-   per-relation configuration parameters for the autovacuum daemon.
-   If there is an entry here for a particular relation, the given
-   parameters will be used for autovacuuming that table.  If no entry
-   is present, the system-wide defaults will be used. For more information
-   about the autovacuum daemon, see <xref linkend="autovacuum">.
-  </para>
-
-  <note>
-   <para>
-    It is likely that <structname>pg_autovacuum</structname> will disappear
-    in a future release, with the information instead being kept in
-    <structname>pg_class</>.<structfield>reloptions</> entries.
-   </para>
-  </note>
-
-  <table>
-   <title><structname>pg_autovacuum</> Columns</title>
-
-   <tgroup cols="4">
-    <thead>
-     <row>
-      <entry>Name</entry>
-      <entry>Type</entry>
-      <entry>References</entry>
-      <entry>Description</entry>
-     </row>
-    </thead>
-
-    <tbody>
-     <row>
-      <entry><structfield>vacrelid</structfield></entry>
-      <entry><type>oid</type></entry>
-      <entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.oid</literal></entry>
-      <entry>The table this entry is for</entry>
-     </row>
-
-     <row>
-      <entry><structfield>enabled</structfield></entry>
-      <entry><type>bool</type></entry>
-      <entry></entry>
-      <entry>If false, this table will not be autovacuumed, except
-       to prevent transaction ID wraparound</entry>
-     </row>
-
-     <row>
-      <entry><structfield>vac_base_thresh</structfield></entry>
-      <entry><type>integer</type></entry>
-      <entry></entry>
-      <entry>Minimum number of modified tuples before vacuum</entry>
-     </row>
-
-     <row>
-      <entry><structfield>vac_scale_factor</structfield></entry>
-      <entry><type>float4</type></entry>
-      <entry></entry>
-      <entry>Multiplier for <structfield>reltuples</> to add to
-       <structfield>vac_base_thresh</></entry>
-     </row>
-
-     <row>
-      <entry><structfield>anl_base_thresh</structfield></entry>
-      <entry><type>integer</type></entry>
-      <entry></entry>
-      <entry>Minimum number of modified tuples before analyze</entry>
-     </row>
-
-     <row>
-      <entry><structfield>anl_scale_factor</structfield></entry>
-      <entry><type>float4</type></entry>
-      <entry></entry>
-      <entry>Multiplier for <structfield>reltuples</> to add to
-       <structfield>anl_base_thresh</></entry>
-     </row>
-
-     <row>
-      <entry><structfield>vac_cost_delay</structfield></entry>
-      <entry><type>integer</type></entry>
-      <entry></entry>
-      <entry>Custom <varname>vacuum_cost_delay</> parameter</entry>
-     </row>
-
-     <row>
-      <entry><structfield>vac_cost_limit</structfield></entry>
-      <entry><type>integer</type></entry>
-      <entry></entry>
-      <entry>Custom <varname>vacuum_cost_limit</> parameter</entry>
-     </row>
-
-     <row>
-      <entry><structfield>freeze_min_age</structfield></entry>
-      <entry><type>integer</type></entry>
-      <entry></entry>
-      <entry>Custom <varname>vacuum_freeze_min_age</> parameter</entry>
-     </row>
-
-     <row>
-      <entry><structfield>freeze_max_age</structfield></entry>
-      <entry><type>integer</type></entry>
-      <entry></entry>
-      <entry>Custom <varname>autovacuum_freeze_max_age</> parameter</entry>
-     </row>
-
-     <row>
-      <entry><structfield>freeze_table_age</structfield></entry>
-      <entry><type>integer</type></entry>
-      <entry></entry>
-      <entry>Custom <varname>vacuum_freeze_table_age</> parameter</entry>
-     </row>
-    </tbody>
-   </tgroup>
-  </table>
-
-  <para>
-   The autovacuum daemon will initiate a <command>VACUUM</> operation
-   on a particular table when the number of updated or deleted tuples
-   exceeds <structfield>vac_base_thresh</structfield> plus
-   <structfield>vac_scale_factor</structfield> times the number of
-   live tuples currently estimated to be in the relation.
-   Similarly, it will initiate an <command>ANALYZE</> operation
-   when the number of inserted, updated or deleted tuples
-   exceeds <structfield>anl_base_thresh</structfield> plus
-   <structfield>anl_scale_factor</structfield> times the number of
-   live tuples currently estimated to be in the relation.
-  </para>
-
-  <para>
-   Also, the autovacuum daemon will perform a <command>VACUUM</> operation
-   to prevent transaction ID wraparound if the table's
-   <structname>pg_class</>.<structfield>relfrozenxid</> field attains an age
-   of more than <structfield>freeze_max_age</> transactions, whether the table
-   has been changed or not, even if
-   <structname>pg_autovacuum</>.<structfield>enabled</> is set to
-   <literal>false</> for it.  The system will launch autovacuum to perform
-   such <command>VACUUM</>s even if autovacuum is otherwise disabled.
-   See <xref linkend="vacuum-for-wraparound"> for more about wraparound
-   prevention.
-  </para>
-
-  <para>
-   Any of the numerical fields can contain <literal>-1</> (or indeed
-   any negative value) to indicate that the system-wide default should
-   be used for this particular value.  Observe that the
-   <structfield>vac_cost_delay</> variable inherits its default value from the
-   <xref linkend="guc-autovacuum-vacuum-cost-delay"> configuration parameter,
-   or from <xref linkend="guc-vacuum-cost-delay"> if the former is set to a
-   negative value.  The same applies to <structfield>vac_cost_limit</>.
-   Also, autovacuum will ignore attempts to set a per-table
-   <structfield>freeze_max_age</> larger than the system-wide setting (it can
-   only be set smaller), and the <structfield>freeze_min_age</> value will be
-   limited to half the system-wide <xref
-   linkend="guc-autovacuum-freeze-max-age"> setting.  Note that while you
-   can set <structfield>freeze_max_age</> very small, or even zero, this
-   is usually unwise since it will force frequent vacuuming.
-  </para>
-
- </sect1>
-
-
  <sect1 id="catalog-pg-cast">
   <title><structname>pg_cast</structname></title>
 
index 0b77731e3411c30a26de6fc2f7ebde1e974c7257..7a4786fcf586c391390a30d4f14db9753bd54edc 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.206 2009/01/16 13:27:23 heikki Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.207 2009/02/09 20:57:59 alvherre Exp $ -->
 
 <chapter Id="runtime-config">
   <title>Server Configuration</title>
@@ -3547,8 +3547,8 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;
         The default is 50 tuples.
         This parameter can only be set in the <filename>postgresql.conf</>
         file or on the server command line.
-        This setting can be overridden for individual tables by entries in
-        <structname>pg_autovacuum</>.
+        This setting can be overridden for individual tables by
+        changing storage parameters.
        </para>
       </listitem>
      </varlistentry>
@@ -3565,8 +3565,8 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;
         The default is 50 tuples.
         This parameter can only be set in the <filename>postgresql.conf</>
         file or on the server command line.
-        This setting can be overridden for individual tables by entries in
-        <structname>pg_autovacuum</>.
+        This setting can be overridden for individual tables by
+        changing storage parameters.
        </para>
       </listitem>
      </varlistentry>
@@ -3584,8 +3584,8 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;
         The default is 0.2 (20% of table size).
         This parameter can only be set in the <filename>postgresql.conf</>
         file or on the server command line.
-        This setting can be overridden for individual tables by entries in
-        <structname>pg_autovacuum</>.
+        This setting can be overridden for individual tables by
+        changing storage parameters.
        </para>
       </listitem>
      </varlistentry>
@@ -3603,8 +3603,8 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;
         The default is 0.1 (10% of table size).
         This parameter can only be set in the <filename>postgresql.conf</>
         file or on the server command line.
-        This setting can be overridden for individual tables by entries in
-        <structname>pg_autovacuum</>.
+        This setting can be overridden for individual tables by
+        changing storage parameters.
        </para>
       </listitem>
      </varlistentry>
@@ -3624,8 +3624,8 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;
         autovacuum is otherwise disabled.
         The default is 200 million transactions.
         This parameter can only be set at server start, but the setting
-        can be reduced for individual tables by entries in
-        <structname>pg_autovacuum</>.
+        can be reduced for individual tables by
+        changing storage parameters.
         For more information see <xref linkend="vacuum-for-wraparound">.
        </para>
       </listitem>
@@ -3645,8 +3645,8 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;
         The default value is 20 milliseconds.
         This parameter can only be set in the <filename>postgresql.conf</>
         file or on the server command line.
-        This setting can be overridden for individual tables by entries in
-        <structname>pg_autovacuum</>.
+        This setting can be overridden for individual tables by
+        changing storage parameters.
        </para>
       </listitem>
      </varlistentry>
@@ -3667,8 +3667,8 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;
         each worker never exceeds the limit on this variable.
         This parameter can only be set in the <filename>postgresql.conf</>
         file or on the server command line.
-        This setting can be overridden for individual tables by entries in
-        <structname>pg_autovacuum</>.
+        This setting can be overridden for individual tables by
+        changing storage parameters.
        </para>
       </listitem>
      </varlistentry>
index ad9c38da55b862d7271bc4bba64a21c46580f6de..2b6f53bcffaeb0f73f539a07f01fc4288abf0c8f 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/maintenance.sgml,v 1.89 2009/01/16 13:27:23 heikki Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/maintenance.sgml,v 1.90 2009/02/09 20:57:59 alvherre Exp $ -->
 
 <chapter id="maintenance">
  <title>Routine Database Maintenance Tasks</title>
@@ -573,7 +573,9 @@ HINT:  Stop the postmaster and use a standalone backend to VACUUM in "mydb".
    <para>
     Tables whose <structfield>relfrozenxid</> value is more than
     <varname>autovacuum_freeze_max_age</> transactions old are always
-    vacuumed.  Otherwise, if the number of tuples obsoleted since the last
+    vacuumed (this also applies to those tables whose freeze max age has
+    been modified via storage parameters; see below).  Otherwise, if the
+    number of tuples obsoleted since the last
     <command>VACUUM</command> exceeds the <quote>vacuum threshold</quote>, the
     table is vacuumed.  The vacuum threshold is defined as:
 <programlisting>
@@ -604,65 +606,39 @@ analyze threshold = analyze base threshold + analyze scale factor * number of tu
    <para>
     The default thresholds and scale factors are taken from
     <filename>postgresql.conf</filename>, but it is possible to override them
-    on a table-by-table basis by making entries in the system catalog
-    <link
-    linkend="catalog-pg-autovacuum"><structname>pg_autovacuum</></link>.
-    If a <structname>pg_autovacuum</structname> row exists for a particular
-    table, the settings it specifies are applied; otherwise the global
-    settings are used.  See <xref linkend="runtime-config-autovacuum"> for
+    on a table-by-table basis; see 
+    <xref linkend="sql-createtable-storage-parameters"
+    endterm="sql-createtable-storage-parameters-title"> for more information.
+    If a setting
+    has been changed via storage parameters, that value is used; otherwise the
+    global settings are used. See <xref linkend="runtime-config-autovacuum"> for
     more details on the global settings.
    </para>
 
    <para>
-    Besides the base threshold values and scale factors, there are five
-    more parameters that can be set for each table in
-    <structname>pg_autovacuum</structname>.
-    The first, <structname>pg_autovacuum</>.<structfield>enabled</>,
+    Besides the base threshold values and scale factors, there are six
+    more autovacuum parameters that can be set for each table via
+    storage parameters.
+    The first parameter, <literal>autovacuum_enabled</>,
     can be set to <literal>false</literal> to instruct the autovacuum daemon
     to skip that particular table entirely.  In this case
     autovacuum will only touch the table if it must do so
     to prevent transaction ID wraparound.
-    The next two parameters, the vacuum cost delay
-    (<structname>pg_autovacuum</structname>.<structfield>vac_cost_delay</structfield>)
-    and the vacuum cost limit
-    (<structname>pg_autovacuum</structname>.<structfield>vac_cost_limit</structfield>),
-    are used to set table-specific values for the
-    <xref linkend="runtime-config-resource-vacuum-cost" endterm="runtime-config-resource-vacuum-cost-title">
+    Another two parameters,
+    <literal>autovacuum_vacuum_cost_delay</literal> and
+    <literal>autovacuum_vacuum_cost_limit</literal>, are used to set
+    table-specific values for the
+    <xref linkend="runtime-config-resource-vacuum-cost"
+    endterm="runtime-config-resource-vacuum-cost-title">
     feature.
-    The last two parameters,
-    (<structname>pg_autovacuum</structname>.<structfield>freeze_min_age</structfield>)
-    and
-    (<structname>pg_autovacuum</structname>.<structfield>freeze_max_age</structfield>),
-    are used to set table-specific values for
-    <xref linkend="guc-vacuum-freeze-min-age"> and
-    <xref linkend="guc-autovacuum-freeze-max-age"> respectively.
+    <literal>autovacuum_freeze_min_age</literal>,
+    <literal>autovacuum_freeze_max_age</literal> and
+    <literal>autovacuum_freeze_table_age</literal> are used to set
+    values for <xref linkend="guc-vacuum-freeze-min-age">,
+    <xref linkend="guc-autovacuum-freeze-max-age"> and
+    <xref linkend="guc-vacuum-freeze-table-age"> respectively.
    </para>
 
-   <para>
-    If any of the values in <structname>pg_autovacuum</structname>
-    are set to a negative number, or if a row is not present at all in
-    <structname>pg_autovacuum</structname> for any particular table, the
-    corresponding values from <filename>postgresql.conf</filename> are used.
-   </para>
-
-   <para>
-    There is not currently any support for making
-    <structname>pg_autovacuum</structname> entries, except by doing
-    manual <command>INSERT</>s into the catalog.  This feature will be
-    improved in future releases, and it is likely that the catalog
-    definition will change.
-   </para>
-
-   <caution>
-    <para>
-     The contents of the <structname>pg_autovacuum</structname> system
-     catalog are currently not saved in database dumps created by the
-     tools <application>pg_dump</> and <application>pg_dumpall</>.  If
-     you want to preserve them across a dump/reload cycle, make sure
-     you dump the catalog manually.
-    </para>
-   </caution>
-
    <para>
     When multiple workers are running, the cost limit is
     <quote>balanced</quote> among all the running workers, so that the
index b19c89f421141098900ffb212368a227fffb7547..a86ffbba811156d27b698277aee98e193216baaa 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/alter_table.sgml,v 1.102 2008/12/13 19:13:44 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/alter_table.sgml,v 1.103 2009/02/09 20:57:59 alvherre Exp $
 PostgreSQL documentation
 -->
 
@@ -286,7 +286,8 @@ where <replaceable class="PARAMETER">action</replaceable> is one of:
     <listitem>
      <para>
       This form changes one or more storage parameters for the table.  See
-      <xref linkend="SQL-CREATETABLE" endterm="sql-createtable-title">
+      <xref linkend="SQL-CREATETABLE-storage-parameters"
+      endterm="sql-createtable-storage-parameters-title">
       for details on the available parameters.  Note that the table contents
       will not be modified immediately by this command; depending on the
       parameter you might need to rewrite the table to get the desired effects.
index 285ed5bd2e95b6ad0634987514ecb3bd2fe43bc4..704378266541e81c8916facdea25532918ee69c7 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/create_table.sgml,v 1.112 2009/02/02 19:31:38 alvherre Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/create_table.sgml,v 1.113 2009/02/09 20:57:59 alvherre Exp $
 PostgreSQL documentation
 -->
 
@@ -685,19 +685,29 @@ and <replaceable class="PARAMETER">table_constraint</replaceable> is:
   <refsect2 id="SQL-CREATETABLE-storage-parameters">
    <title id="SQL-CREATETABLE-storage-parameters-title">Storage Parameters</title>
 
+ <indexterm zone="sql-createtable-storage-parameters">
+  <primary>storage parameters</primary>
+ </indexterm>
+
    <para>
     The <literal>WITH</> clause can specify <firstterm>storage parameters</>
     for tables, and for indexes associated with a <literal>UNIQUE</literal> or
     <literal>PRIMARY KEY</literal> constraint.  Storage parameters for
     indexes are documented in <xref linkend="SQL-CREATEINDEX"
     endterm="sql-createindex-title">.  The storage parameters currently
-    available for tables are:
+    available for tables are listed below.  For each parameter, there is an
+    additional, identically named parameter, prefixed with
+       <literal>toast.</literal> which can be used to control the behavior of the
+    supplementary storage table, if any; see <xref linkend="storage-toast">.
+       Note that the supplementary storage table inherits the
+    <literal>autovacuum</literal> values from its parent table, if there are
+    no <literal>toast.autovacuum_*</literal> settings set.
    </para>
 
    <variablelist>
 
    <varlistentry>
-    <term><literal>FILLFACTOR</></term>
+    <term><literal>fillfactor</>, <literal>toast.fillfactor</literal> (<type>integer</>)</term>
     <listitem>
      <para>
       The fillfactor for a table is a percentage between 10 and 100.
@@ -715,11 +725,118 @@ and <replaceable class="PARAMETER">table_constraint</replaceable> is:
    </varlistentry>
 
    <varlistentry>
-    <term><literal>TOAST.FILLFACTOR</literal></term>
+    <term><literal>autovacuum_enabled</>, <literal>toast.autovacuum_enabled</literal> (<type>boolean</>)</term>
+    <listitem>
+     <para>
+     Enables or disables the autovacuum daemon on a particular table.
+     If true, the autovacuum daemon will initiate a <command>VACUUM</> operation
+     on a particular table when the number of updated or deleted tuples exceeds 
+     <literal>autovacuum_vacuum_threshold</> plus 
+     <literal>autovacuum_vacuum_scale_factor</> times the number of live tuples 
+     currently estimated to be in the relation.
+     Similarly, it will initiate an <command>ANALYZE</> operation when the
+     number of inserted, updated or deleted tuples exceeds
+     <literal>autovacuum_analyze_threshold</> plus 
+     <literal>autovacuum_analyze_scale_factor</> times the number of live tuples 
+     currently estimated to be in the relation.
+     If false, this table will not be autovacuumed, except to prevent
+     transaction Id wraparound. See <xref linkend="vacuum-for-wraparound"> for
+     more about wraparound prevention.
+     Observe that this variable inherits its value from the <xref
+     linkend="guc-autovacuum"> setting.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><literal>autovacuum_vacuum_threshold</>, <literal>toast.autovacuum_vacuum_threshold</literal> (<type>integer</>)</term>
+    <listitem>
+     <para>
+     Minimum number of updated or deleted tuples before initiate a
+     <command>VACUUM</> operation on a particular table. 
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><literal>autovacuum_vacuum_scale_factor</>, <literal>toast.autovacuum_vacuum_scale_factor</literal> (<type>float4</>)</term>
+    <listitem>
+     <para>
+     Multiplier for <structfield>reltuples</> to add to
+     <literal>autovacuum_vacuum_threshold</>.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><literal>autovacuum_analyze_threshold</>, <literal>toast.autovacuum_analyze_threshold</literal> (<type>integer</>)</term>
+    <listitem>
+     <para>
+     Minimum number of inserted, updated, or deleted tuples before initiate an
+     <command>ANALYZE</> operation on a particular table.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><literal>autovacuum_analyze_scale_factor</>, <literal>toast.autovacuum_analyze_scale_factor</literal> (<type>float4</>)</term>
+    <listitem>
+     <para>
+     Multiplier for <structfield>reltuples</> to add to
+     <literal>autovacuum_analyze_threshold</>.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><literal>autovacuum_vacuum_cost_delay</>, <literal>toast.autovacuum_vacuum_cost_delay</literal> (<type>integer</>)</term>
+    <listitem>
+     <para>
+     Custom <xref linkend="guc-autovacuum-vacuum-cost-delay"> parameter.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><literal>autovacuum_vacuum_cost_limit</>, <literal>toast.autovacuum_vacuum_cost_limit</literal> (<type>integer</>)</term>
+    <listitem>
+     <para>
+     Custom <xref linkend="guc-autovacuum-vacuum-cost-limit"> parameter.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><literal>autovacuum_freeze_min_age</>, <literal>toast.autovacuum_freeze_min_age</literal> (<type>integer</>)</term>
+    <listitem>
+     <para>
+     Custom <xref linkend="guc-vacuum-freeze-min-age"> parameter. Note that
+     autovacuum will ignore attempts to set a per-table
+     <literal>autovacuum_freeze_min_age</> larger than the half system-wide 
+     <xref linkend="guc-autovacuum-freeze-max-age"> setting.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><literal>autovacuum_freeze_max_age</>, <literal>toast.autovacuum_freeze_max_age</literal> (<type>integer</>)</term>
+    <listitem>
+     <para>
+     Custom <xref linkend="guc-autovacuum-freeze-max-age"> parameter. Note that
+     autovacuum will ignore attempts to set a per-table
+     <literal>autovacuum_freeze_max_age</> larger than the system-wide setting
+     (it can only be set smaller). Note that while you can set
+     <literal>autovacuum_freeze_max_age</> very small, or even zero, this is
+     usually unwise since it will force frequent vacuuming.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><literal>autovacuum_freeze_table_age</literal> (<type>integer</type>)</term>
     <listitem>
      <para>
-      Same as above, for the supplementary storage table, if any; see
-      <xref linkend="storage-toast">.
+      Custom <xref linkend="guc-vacuum-freeze-table-age"> parameter.
      </para>
     </listitem>
    </varlistentry>
index e566a136442bc325593be9247e81473a6515d889..548c0b00de84bac3832cc79cdb219f6b1dfdb3dc 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/common/reloptions.c,v 1.20 2009/02/02 19:31:38 alvherre Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/common/reloptions.c,v 1.21 2009/02/09 20:57:59 alvherre Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 static relopt_bool boolRelOpts[] =
 {
+       {
+               {
+                       "autovacuum_enabled",
+                       "Enables autovacuum in this relation",
+                       RELOPT_KIND_HEAP
+               },
+               true
+       },
        /* list terminator */
        { { NULL } }
 };
@@ -86,12 +94,83 @@ static relopt_int intRelOpts[] =
                },
                GIST_DEFAULT_FILLFACTOR, GIST_MIN_FILLFACTOR, 100
        },
+       {
+               {
+                       "autovacuum_vacuum_threshold",
+                       "Minimum number of tuple updates or deletes prior to vacuum",
+                       RELOPT_KIND_HEAP
+               },
+               50, 0, INT_MAX
+       },
+       {
+               {
+                       "autovacuum_analyze_threshold",
+                       "Minimum number of tuple inserts, updates or deletes prior to analyze",
+                       RELOPT_KIND_HEAP
+               },
+               50, 0, INT_MAX
+       },
+       {
+               {
+                       "autovacuum_vacuum_cost_delay",
+                       "Vacuum cost delay in milliseconds, for autovacuum",
+                       RELOPT_KIND_HEAP
+               },
+               20, 0, 1000
+       },
+       {
+               {
+                       "autovacuum_vacuum_cost_limit",
+                       "Vacuum cost amount available before napping, for autovacuum",
+                       RELOPT_KIND_HEAP
+               },
+               200, 1, 10000
+       },
+       {
+               {
+                       "autovacuum_freeze_min_age",
+                       "Minimum age at which VACUUM should freeze a table row, for autovacuum",
+                       RELOPT_KIND_HEAP
+               },
+               100000000, 0, 1000000000
+       },
+       {
+               {
+                       "autovacuum_freeze_max_age",
+                       "Age at which to autovacuum a table to prevent transaction ID wraparound",
+                       RELOPT_KIND_HEAP
+               },
+               200000000, 100000000, 2000000000
+       },
+       {
+               {
+                       "autovacuum_freeze_table_age",
+                       "Age at which VACUUM should perform a full table sweep to replace old Xid values with FrozenXID",
+                       RELOPT_KIND_HEAP
+               }, 150000000, 0, 2000000000
+       },
        /* list terminator */
        { { NULL } }
 };
 
 static relopt_real realRelOpts[] =
 {
+       {
+               {
+                       "autovacuum_vacuum_scale_factor",
+                       "Number of tuple updates or deletes prior to vacuum as a fraction of reltuples",
+                       RELOPT_KIND_HEAP
+               },
+               0.2, 0.0, 100.0
+       },
+       {
+               {
+                       "autovacuum_analyze_scale_factor",
+                       "Number of tuple inserts, updates or deletes prior to analyze as a fraction of reltuples",
+                       RELOPT_KIND_HEAP
+               },
+               0.1, 0.0, 100.0
+       },
        /* list terminator */
        { { NULL } }
 };
@@ -973,7 +1052,8 @@ fillRelOptions(void *rdopts, Size basesize, relopt_value *options,
 
 
 /*
- * Option parser for anything that uses StdRdOptions (i.e. fillfactor only)
+ * Option parser for anything that uses StdRdOptions (i.e. fillfactor and
+ * autovacuum)
  */
 bytea *
 default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
@@ -982,7 +1062,27 @@ default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
        StdRdOptions   *rdopts;
        int                             numoptions;
        relopt_parse_elt tab[] = {
-               {"fillfactor", RELOPT_TYPE_INT, offsetof(StdRdOptions, fillfactor)}
+               {"fillfactor", RELOPT_TYPE_INT, offsetof(StdRdOptions, fillfactor)},
+               {"autovacuum_enabled", RELOPT_TYPE_BOOL,
+                       offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, enabled)},
+               {"autovacuum_vacuum_threshold", RELOPT_TYPE_INT,
+                       offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_threshold)},
+               {"autovacuum_analyze_threshold", RELOPT_TYPE_INT,
+                       offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, analyze_threshold)},
+               {"autovacuum_vacuum_cost_delay", RELOPT_TYPE_INT,
+                       offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_cost_delay)},
+               {"autovacuum_vacuum_cost_limit", RELOPT_TYPE_INT,
+                       offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_cost_limit)},
+               {"autovacuum_freeze_min_age", RELOPT_TYPE_INT,
+                       offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, freeze_min_age)},
+               {"autovacuum_freeze_max_age", RELOPT_TYPE_INT,
+                       offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, freeze_max_age)},
+               {"autovacuum_freeze_table_age", RELOPT_TYPE_INT,
+                       offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, freeze_table_age)},
+               {"autovacuum_vacuum_scale_factor", RELOPT_TYPE_REAL,
+                       offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_scale_factor)},
+               {"autovacuum_analyze_scale_factor", RELOPT_TYPE_REAL,
+                       offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, analyze_scale_factor)}
        };
 
        options = parseRelOptions(reloptions, validate, kind, &numoptions);
index 58973c9a88991588372d59b42e8ddae702447d84..9a828d66fe19a693bd47826a4614ce649550bedc 100644 (file)
@@ -2,7 +2,7 @@
 #
 # Makefile for backend/catalog
 #
-# $PostgreSQL: pgsql/src/backend/catalog/Makefile,v 1.68 2008/12/19 16:25:16 petere Exp $
+# $PostgreSQL: pgsql/src/backend/catalog/Makefile,v 1.69 2009/02/09 20:57:59 alvherre Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -26,7 +26,7 @@ all: $(BKIFILES)
 # indexing.h had better be last, and toasting.h just before it.
 
 POSTGRES_BKI_SRCS = $(addprefix $(top_srcdir)/src/include/catalog/,\
-       pg_proc.h pg_type.h pg_attribute.h pg_class.h pg_autovacuum.h \
+       pg_proc.h pg_type.h pg_attribute.h pg_class.h \
        pg_attrdef.h pg_constraint.h pg_inherits.h pg_index.h pg_operator.h \
        pg_opfamily.h pg_opclass.h pg_am.h pg_amop.h pg_amproc.h \
        pg_language.h pg_largeobject.h pg_aggregate.h pg_statistic.h \
index ed77c51c9fff116370a598c7b46a1be9bdd24b18..e7aea7fc23c9e9ebecc661fe93a86b76150a7a0c 100644 (file)
@@ -55,7 +55,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.92 2009/01/16 13:27:24 heikki Exp $
+ *       $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.93 2009/02/09 20:57:59 alvherre Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include "access/genam.h"
 #include "access/heapam.h"
+#include "access/reloptions.h"
 #include "access/transam.h"
 #include "access/xact.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/namespace.h"
-#include "catalog/pg_autovacuum.h"
 #include "catalog/pg_database.h"
 #include "commands/dbcommands.h"
 #include "commands/vacuum.h"
@@ -165,13 +165,15 @@ typedef struct av_relation
 {
        Oid                     ar_toastrelid;  /* hash key - must be first */
        Oid                     ar_relid;
+       bool            ar_hasrelopts;
+       AutoVacOpts     ar_reloptions;  /* copy of AutoVacOpts from the main table's
+                                                                  reloptions, or NULL if none */
 } av_relation;
 
 /* struct to keep track of tables to vacuum and/or analyze, after rechecking */
 typedef struct autovac_table
 {
        Oid                     at_relid;
-       Oid                     at_toastrelid;
        bool            at_dovacuum;
        bool            at_doanalyze;
        int                     at_freeze_min_age;
@@ -282,16 +284,17 @@ static void autovac_balance_cost(void);
 static void do_autovacuum(void);
 static void FreeWorkerInfo(int code, Datum arg);
 
-static autovac_table *table_recheck_autovac(Oid relid, HTAB *table_toast_map);
-static void relation_needs_vacanalyze(Oid relid, Form_pg_autovacuum avForm,
+static autovac_table *table_recheck_autovac(Oid relid, HTAB *table_toast_map,
+                                         TupleDesc pg_class_desc);
+static void relation_needs_vacanalyze(Oid relid, AutoVacOpts *relopts,
                                                  Form_pg_class classForm,
-                                                 PgStat_StatTabEntry *tabentry, bool *dovacuum,
-                                                 bool *doanalyze, bool *wraparound);
+                                                 PgStat_StatTabEntry *tabentry,
+                                                 bool *dovacuum, bool *doanalyze, bool *wraparound);
 
 static void autovacuum_do_vac_analyze(autovac_table *tab,
                                                  BufferAccessStrategy bstrategy);
-static HeapTuple get_pg_autovacuum_tuple_relid(Relation avRel, Oid relid,
-                                                                                          HTAB *table_toast_map);
+static AutoVacOpts *extract_autovac_opts(HeapTuple tup,
+                                        TupleDesc pg_class_desc);
 static PgStat_StatTabEntry *get_pgstat_tabentry_relid(Oid relid, bool isshared,
                                                  PgStat_StatDBEntry *shared,
                                                  PgStat_StatDBEntry *dbentry);
@@ -1816,8 +1819,7 @@ get_database_list(void)
 static void
 do_autovacuum(void)
 {
-       Relation        classRel,
-                               avRel;
+       Relation        classRel;
        HeapTuple       tuple;
        HeapScanDesc relScan;
        Form_pg_database dbForm;
@@ -1829,6 +1831,7 @@ do_autovacuum(void)
        PgStat_StatDBEntry *dbentry;
        BufferAccessStrategy bstrategy;
        ScanKeyData     key;
+       TupleDesc       pg_class_desc;
 
        /*
         * StartTransactionCommand and CommitTransactionCommand will automatically
@@ -1890,12 +1893,14 @@ do_autovacuum(void)
        shared = pgstat_fetch_stat_dbentry(InvalidOid);
 
        classRel = heap_open(RelationRelationId, AccessShareLock);
-       avRel = heap_open(AutovacuumRelationId, AccessShareLock);
+
+       /* create a copy so we can use it after closing pg_class */
+       pg_class_desc = CreateTupleDescCopy(RelationGetDescr(classRel));
 
        /* create hash table for toast <-> main relid mapping */
        MemSet(&ctl, 0, sizeof(ctl));
        ctl.keysize = sizeof(Oid);
-       ctl.entrysize = sizeof(Oid) * 2;
+       ctl.entrysize = sizeof(av_relation);
        ctl.hash = oid_hash;
 
        table_toast_map = hash_create("TOAST to main relid map",
@@ -1909,9 +1914,9 @@ do_autovacuum(void)
         * We do this in two passes: on the first one we collect the list of
         * plain relations, and on the second one we collect TOAST tables.
         * The reason for doing the second pass is that during it we want to use
-        * the main relation's pg_autovacuum entry if the TOAST table does not have
-        * any, and we cannot obtain it unless we know beforehand what's the main
-        * table OID.
+        * the main relation's pg_class.reloptions entry if the TOAST table does
+        * not have any, and we cannot obtain it unless we know beforehand what's
+        * the main table OID.
         *
         * We need to check TOAST tables separately because in cases with short,
         * wide tables there might be proportionally much more activity in the
@@ -1931,9 +1936,8 @@ do_autovacuum(void)
        while ((tuple = heap_getnext(relScan, ForwardScanDirection)) != NULL)
        {
                Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple);
-               Form_pg_autovacuum avForm = NULL;
                PgStat_StatTabEntry *tabentry;
-               HeapTuple       avTup;
+               AutoVacOpts *relopts;
                Oid                     relid;
                bool            dovacuum;
                bool            doanalyze;
@@ -1942,17 +1946,13 @@ do_autovacuum(void)
 
                relid = HeapTupleGetOid(tuple);
 
-               /* Fetch the pg_autovacuum tuple for the relation, if any */
-               avTup = get_pg_autovacuum_tuple_relid(avRel, relid, NULL);
-               if (HeapTupleIsValid(avTup))
-                       avForm = (Form_pg_autovacuum) GETSTRUCT(avTup);
-
-               /* Fetch the pgstat entry for this table */
+               /* Fetch reloptions and the pgstat entry for this table */
+               relopts = extract_autovac_opts(tuple, pg_class_desc);
                tabentry = get_pgstat_tabentry_relid(relid, classForm->relisshared,
                                                                                         shared, dbentry);
 
                /* Check if it needs vacuum or analyze */
-               relation_needs_vacanalyze(relid, avForm, classForm, tabentry,
+               relation_needs_vacanalyze(relid, relopts, classForm, tabentry,
                                                                  &dovacuum, &doanalyze, &wraparound);
 
                /*
@@ -1998,7 +1998,7 @@ do_autovacuum(void)
                }
                else
                {
-                       /* Plain relations that need work are added to table_oids */
+                       /* relations that need work are added to table_oids */
                        if (dovacuum || doanalyze)
                                table_oids = lappend_oid(table_oids, relid);
 
@@ -2020,12 +2020,16 @@ do_autovacuum(void)
                                {
                                        /* hash_search already filled in the key */
                                        hentry->ar_relid = relid;
+                                       hentry->ar_hasrelopts = false;
+                                       if (relopts != NULL)
+                                       {
+                                               hentry->ar_hasrelopts = true;
+                                               memcpy(&hentry->ar_reloptions, relopts,
+                                                          sizeof(AutoVacOpts));
+                                       }
                                }
                        }
                }
-
-               if (HeapTupleIsValid(avTup))
-                       heap_freetuple(avTup);
        }
 
        heap_endscan(relScan);
@@ -2040,10 +2044,9 @@ do_autovacuum(void)
        while ((tuple = heap_getnext(relScan, ForwardScanDirection)) != NULL)
        {
                Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple);
-               Form_pg_autovacuum avForm = NULL;
                PgStat_StatTabEntry *tabentry;
-               HeapTuple   avTup;
                Oid         relid;
+               AutoVacOpts *relopts = NULL;
                bool            dovacuum;
                bool            doanalyze;
                bool            wraparound;
@@ -2057,17 +2060,26 @@ do_autovacuum(void)
 
                relid = HeapTupleGetOid(tuple);
 
-               /* Fetch the pg_autovacuum tuple for this rel */
-               avTup = get_pg_autovacuum_tuple_relid(avRel, relid, table_toast_map);
+               /*
+                * fetch reloptions -- if this toast table does not have them,
+                * try the main rel
+                */
+               relopts = extract_autovac_opts(tuple, pg_class_desc);
+               if (relopts == NULL)
+               {
+                       av_relation             *hentry;
+                       bool                    found;
 
-               if (HeapTupleIsValid(avTup))
-                       avForm = (Form_pg_autovacuum) GETSTRUCT(avTup);
+                       hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
+                       if (found && hentry->ar_hasrelopts)
+                               relopts = &hentry->ar_reloptions;
+               }
 
                /* Fetch the pgstat entry for this table */
                tabentry = get_pgstat_tabentry_relid(relid, classForm->relisshared,
                                                                                         shared, dbentry);
 
-               relation_needs_vacanalyze(relid, avForm, classForm, tabentry,
+               relation_needs_vacanalyze(relid, relopts, classForm, tabentry,
                                                                  &dovacuum, &doanalyze, &wraparound);
 
                /* ignore analyze for toast tables */
@@ -2076,7 +2088,6 @@ do_autovacuum(void)
        }
 
        heap_endscan(relScan);
-       heap_close(avRel, AccessShareLock);
        heap_close(classRel, AccessShareLock);
 
        /*
@@ -2163,10 +2174,10 @@ do_autovacuum(void)
                 * condition is not closed but it is very small.
                 */
                MemoryContextSwitchTo(AutovacMemCxt);
-               tab = table_recheck_autovac(relid, table_toast_map);
+               tab = table_recheck_autovac(relid, table_toast_map, pg_class_desc);
                if (tab == NULL)
                {
-                       /* someone else vacuumed the table */
+                       /* someone else vacuumed the table, or it went away */
                        LWLockRelease(AutovacuumScheduleLock);
                        continue;
                }
@@ -2292,49 +2303,29 @@ deleted:
 }
 
 /*
- * Returns a copy of the pg_autovacuum tuple for the given relid, or NULL if
- * there isn't any.  avRel is pg_autovacuum, already open and suitably locked.
+ * extract_autovac_opts
  *
- * If table_toast_map is not null, use it to find an alternative OID with which
- * to search a pg_autovacuum entry, if the passed relid does not yield one
- * directly.
+ * Given a relation's pg_class tuple, return the AutoVacOpts portion of
+ * reloptions, if set; otherwise, return NULL.
  */
-static HeapTuple
-get_pg_autovacuum_tuple_relid(Relation avRel, Oid relid,
-                                                         HTAB *table_toast_map)
+AutoVacOpts *
+extract_autovac_opts(HeapTuple tup, TupleDesc pg_class_desc)
 {
-       ScanKeyData entry[1];
-       SysScanDesc avScan;
-       HeapTuple       avTup;
+       bytea      *relopts;
+       AutoVacOpts *av;
 
-       ScanKeyInit(&entry[0],
-                               Anum_pg_autovacuum_vacrelid,
-                               BTEqualStrategyNumber, F_OIDEQ,
-                               ObjectIdGetDatum(relid));
+       Assert(((Form_pg_class) GETSTRUCT(tup))->relkind == RELKIND_RELATION ||
+                  ((Form_pg_class) GETSTRUCT(tup))->relkind == RELKIND_TOASTVALUE);
 
-       avScan = systable_beginscan(avRel, AutovacuumRelidIndexId, true,
-                                                               SnapshotNow, 1, entry);
-
-       avTup = systable_getnext(avScan);
-
-       if (HeapTupleIsValid(avTup))
-               avTup = heap_copytuple(avTup);
-
-       systable_endscan(avScan);
-
-       if (!HeapTupleIsValid(avTup) && table_toast_map != NULL)
-       {
-               av_relation             *hentry;
-               bool            found;
-
-               hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
-               if (found)
-                       /* avoid second recursion */
-                       avTup = get_pg_autovacuum_tuple_relid(avRel, hentry->ar_relid,
-                                                                                                 NULL);
-       }
+       relopts = extractRelOptions(tup, pg_class_desc, InvalidOid);
+       if (relopts == NULL)
+               return NULL;
+       
+       av = palloc(sizeof(AutoVacOpts));
+       memcpy(av, &(((StdRdOptions *) relopts)->autovacuum), sizeof(AutoVacOpts));
+       pfree(relopts);
 
-       return avTup;
+       return av;
 }
 
 /*
@@ -2370,13 +2361,11 @@ get_pgstat_tabentry_relid(Oid relid, bool isshared, PgStat_StatDBEntry *shared,
  * Note that the returned autovac_table does not have the name fields set.
  */
 static autovac_table *
-table_recheck_autovac(Oid relid, HTAB *table_toast_map)
+table_recheck_autovac(Oid relid, HTAB *table_toast_map,
+                                         TupleDesc pg_class_desc)
 {
-       Form_pg_autovacuum avForm = NULL;
        Form_pg_class classForm;
        HeapTuple       classTup;
-       HeapTuple       avTup;
-       Relation        avRel;
        bool            dovacuum;
        bool            doanalyze;
        autovac_table *tab = NULL;
@@ -2384,6 +2373,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map)
        PgStat_StatDBEntry *shared;
        PgStat_StatDBEntry *dbentry;
        bool            wraparound;
+       AutoVacOpts     *avopts;
 
        /* use fresh stats */
        autovac_refresh_stats();
@@ -2399,23 +2389,27 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map)
                return NULL;
        classForm = (Form_pg_class) GETSTRUCT(classTup);
 
-       /*
-        * Fetch the pg_autovacuum entry, if any.  For a toast table, also try the
-        * main rel's pg_autovacuum entry if there isn't one for the TOAST table
-        * itself.
+       /* 
+        * Get the applicable reloptions.  If it is a TOAST table, try to get the
+        * main table reloptions if the toast table itself doesn't have.
         */
-       avRel = heap_open(AutovacuumRelationId, AccessShareLock);
-       avTup = get_pg_autovacuum_tuple_relid(avRel, relid,
-                       classForm->relkind == RELKIND_TOASTVALUE ? table_toast_map : NULL);
+       avopts = extract_autovac_opts(classTup, pg_class_desc);
+       if (classForm->relkind == RELKIND_TOASTVALUE && 
+               avopts == NULL && table_toast_map != NULL)
+       {
+               av_relation             *hentry;
+               bool                    found;
 
-       if (HeapTupleIsValid(avTup))
-               avForm = (Form_pg_autovacuum) GETSTRUCT(avTup);
+               hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
+               if (found && hentry->ar_hasrelopts)
+                       avopts = &hentry->ar_reloptions;
+       }
 
        /* fetch the pgstat table entry */
        tabentry = get_pgstat_tabentry_relid(relid, classForm->relisshared,
                                                                                 shared, dbentry);
 
-       relation_needs_vacanalyze(relid, avForm, classForm, tabentry,
+       relation_needs_vacanalyze(relid, avopts, classForm, tabentry,
                                                          &dovacuum, &doanalyze, &wraparound);
 
        /* ignore ANALYZE for toast tables */
@@ -2431,41 +2425,28 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map)
                int                     vac_cost_delay;
 
                /*
-                * Calculate the vacuum cost parameters and the minimum freeze age. If
-                * there is a tuple in pg_autovacuum, use it; else, use the GUC
-                * defaults.  Note that the fields may contain "-1" (or indeed any
-                * negative value), which means use the GUC defaults for each setting.
-                * In cost_limit, the value 0 also means to use the value from
-                * elsewhere.
+                * Calculate the vacuum cost parameters and the freeze ages.  If there
+                * are options set in pg_class.reloptions, use them; in the case of a
+                * toast table, try the main table too.  Otherwise use the GUC
+                * defaults, autovacuum's own first and plain vacuum second.
                 */
-               if (avForm != NULL)
+               if (avopts)
                {
-                       vac_cost_limit = (avForm->vac_cost_limit > 0) ?
-                               avForm->vac_cost_limit :
-                               ((autovacuum_vac_cost_limit > 0) ?
-                                autovacuum_vac_cost_limit : VacuumCostLimit);
-
-                       vac_cost_delay = (avForm->vac_cost_delay >= 0) ?
-                               avForm->vac_cost_delay :
-                               ((autovacuum_vac_cost_delay >= 0) ?
-                                autovacuum_vac_cost_delay : VacuumCostDelay);
-
-                       freeze_min_age = (avForm->freeze_min_age >= 0) ?
-                               avForm->freeze_min_age : default_freeze_min_age;
-
-                       freeze_table_age = (avForm->freeze_table_age >= 0) ?
-                               avForm->freeze_table_age : default_freeze_table_age;
+                       vac_cost_delay = avopts->vacuum_cost_delay;
+                       vac_cost_limit = avopts->vacuum_cost_limit;
+                       freeze_min_age = avopts->freeze_min_age;
+                       freeze_table_age = avopts->freeze_table_age;
                }
                else
                {
-                       vac_cost_limit = (autovacuum_vac_cost_limit > 0) ?
-                               autovacuum_vac_cost_limit : VacuumCostLimit;
-
-                       vac_cost_delay = (autovacuum_vac_cost_delay >= 0) ?
+                       /* -1 in autovac setting means use plain vacuum_cost_delay */
+                       vac_cost_delay = autovacuum_vac_cost_delay >= 0 ?
                                autovacuum_vac_cost_delay : VacuumCostDelay;
-
+                       /* 0 or -1 in autovac setting means use plain vacuum_cost_limit */
+                       vac_cost_limit = autovacuum_vac_cost_limit > 0 ?
+                               autovacuum_vac_cost_limit : VacuumCostLimit;
+                       /* these do not have autovacuum-specific settings */
                        freeze_min_age = default_freeze_min_age;
-
                        freeze_table_age = default_freeze_table_age;
                }
 
@@ -2483,9 +2464,6 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map)
                tab->at_datname = NULL;
        }
 
-       heap_close(avRel, AccessShareLock);
-       if (HeapTupleIsValid(avTup))
-               heap_freetuple(avTup);
        heap_freetuple(classTup);
 
        return tab;
@@ -2496,8 +2474,12 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map)
  *
  * Check whether a relation needs to be vacuumed or analyzed; return each into
  * "dovacuum" and "doanalyze", respectively.  Also return whether the vacuum is
- * being forced because of Xid wraparound.     avForm and tabentry can be NULL,
- * classForm shouldn't.
+ * being forced because of Xid wraparound.
+ *
+ * relopts is a pointer to the AutoVacOpts options (either for itself in the
+ * case of a plain table, or for either itself or its parent table in the case
+ * of a TOAST table), NULL if none; tabentry is the pgstats entry, which can be
+ * NULL.
  *
  * A table needs to be vacuumed if the number of dead tuples exceeds a
  * threshold.  This threshold is calculated as
@@ -2513,19 +2495,19 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map)
  * We also force vacuum if the table's relfrozenxid is more than freeze_max_age
  * transactions back.
  *
- * A table whose pg_autovacuum.enabled value is false, is automatically
- * skipped (unless we have to vacuum it due to freeze_max_age).  Thus
- * autovacuum can be disabled for specific tables.     Also, when the stats
+ * A table whose autovacuum_enabled option is false is
+ * automatically skipped (unless we have to vacuum it due to freeze_max_age).
+ * Thus autovacuum can be disabled for specific tables.        Also, when the stats
  * collector does not have data about a table, it will be skipped.
  *
- * A table whose vac_base_thresh value is <0 takes the base value from the
+ * A table whose vac_base_thresh value is < 0 takes the base value from the
  * autovacuum_vacuum_threshold GUC variable.  Similarly, a vac_scale_factor
- * value <0 is substituted with the value of
+ * value < 0 is substituted with the value of
  * autovacuum_vacuum_scale_factor GUC variable.  Ditto for analyze.
  */
 static void
 relation_needs_vacanalyze(Oid relid,
-                                                 Form_pg_autovacuum avForm,
+                                                 AutoVacOpts *relopts,
                                                  Form_pg_class classForm,
                                                  PgStat_StatTabEntry *tabentry,
  /* output params below */
@@ -2534,9 +2516,10 @@ relation_needs_vacanalyze(Oid relid,
                                                  bool *wraparound)
 {
        bool            force_vacuum;
+       bool            av_enabled;
        float4          reltuples;              /* pg_class.reltuples */
 
-       /* constants from pg_autovacuum or GUC variables */
+       /* constants from reloptions or GUC variables */
        int                     vac_base_thresh,
                                anl_base_thresh;
        float4          vac_scale_factor,
@@ -2558,36 +2541,28 @@ relation_needs_vacanalyze(Oid relid,
        AssertArg(OidIsValid(relid));
 
        /*
-        * Determine vacuum/analyze equation parameters.  If there is a tuple in
-        * pg_autovacuum, use it; else, use the GUC defaults.  Note that the
-        * fields may contain "-1" (or indeed any negative value), which means use
-        * the GUC defaults for each setting.
+        * Determine vacuum/analyze equation parameters.  We have two possible
+        * sources: the passed reloptions (which could be a main table or a toast
+        * table), or the autovacuum GUC variables.
         */
-       if (avForm != NULL)
+       if (relopts)
        {
-               vac_scale_factor = (avForm->vac_scale_factor >= 0) ?
-                       avForm->vac_scale_factor : autovacuum_vac_scale;
-               vac_base_thresh = (avForm->vac_base_thresh >= 0) ?
-                       avForm->vac_base_thresh : autovacuum_vac_thresh;
-
-               anl_scale_factor = (avForm->anl_scale_factor >= 0) ?
-                       avForm->anl_scale_factor : autovacuum_anl_scale;
-               anl_base_thresh = (avForm->anl_base_thresh >= 0) ?
-                       avForm->anl_base_thresh : autovacuum_anl_thresh;
-
-               freeze_max_age = (avForm->freeze_max_age >= 0) ?
-                       Min(avForm->freeze_max_age, autovacuum_freeze_max_age) :
-                       autovacuum_freeze_max_age;
+               vac_scale_factor = relopts->vacuum_scale_factor;
+               vac_base_thresh = relopts->vacuum_threshold;
+               anl_scale_factor = relopts->analyze_scale_factor;
+               anl_base_thresh = relopts->analyze_threshold;
+               freeze_max_age = Min(relopts->freeze_max_age,
+                                                        autovacuum_freeze_max_age);
+               av_enabled = relopts->enabled;
        }
        else
        {
                vac_scale_factor = autovacuum_vac_scale;
                vac_base_thresh = autovacuum_vac_thresh;
-
                anl_scale_factor = autovacuum_anl_scale;
                anl_base_thresh = autovacuum_anl_thresh;
-
                freeze_max_age = autovacuum_freeze_max_age;
+               av_enabled = true;
        }
 
        /* Force vacuum if table is at risk of wraparound */
@@ -2599,8 +2574,8 @@ relation_needs_vacanalyze(Oid relid,
                                                                                  xidForceLimit));
        *wraparound = force_vacuum;
 
-       /* User disabled it in pg_autovacuum?  (But ignore if at risk) */
-       if (avForm && !avForm->enabled && !force_vacuum)
+       /* User disabled it in pg_class.reloptions?  (But ignore if at risk) */
+       if (!force_vacuum && !av_enabled)
        {
                *doanalyze = false;
                *dovacuum = false;
index 1db49f6a152e6f9a65675b4ef372cadad9abdc38..d02bde48c82acb992c9acbc7e749ce43a6e24385 100644 (file)
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.521 2009/02/06 21:15:11 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.522 2009/02/09 20:57:59 alvherre Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     200902061
+#define CATALOG_VERSION_NO     200902091
 
 #endif
index 1c517c7f3b664f2cdd97bbfe2030c05135b57064..bb5b9eabf63e68e92d1389149997d35eab551eb0 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/indexing.h,v 1.106 2009/01/22 20:16:08 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/indexing.h,v 1.107 2009/02/09 20:57:59 alvherre Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -97,9 +97,6 @@ DECLARE_UNIQUE_INDEX(pg_auth_members_role_member_index, 2694, on pg_auth_members
 DECLARE_UNIQUE_INDEX(pg_auth_members_member_role_index, 2695, on pg_auth_members using btree(member oid_ops, roleid oid_ops));
 #define AuthMemMemRoleIndexId  2695
 
-DECLARE_UNIQUE_INDEX(pg_autovacuum_vacrelid_index, 1250, on pg_autovacuum using btree(vacrelid oid_ops));
-#define AutovacuumRelidIndexId 1250
-
 DECLARE_UNIQUE_INDEX(pg_cast_oid_index, 2660, on pg_cast using btree(oid oid_ops));
 #define CastOidIndexId 2660
 DECLARE_UNIQUE_INDEX(pg_cast_source_target_index, 2661, on pg_cast using btree(castsource oid_ops, casttarget oid_ops));
diff --git a/src/include/catalog/pg_autovacuum.h b/src/include/catalog/pg_autovacuum.h
deleted file mode 100644 (file)
index 94eb05b..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * pg_autovacuum.h
- *       definition of the system "autovacuum" relation (pg_autovacuum)
- *
- * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * $PostgreSQL: pgsql/src/include/catalog/pg_autovacuum.h,v 1.11 2009/01/16 13:27:24 heikki Exp $
- *
- *-------------------------------------------------------------------------
- */
-#ifndef PG_AUTOVACUUM_H
-#define PG_AUTOVACUUM_H
-
-#include "catalog/genbki.h"
-
-/* ----------------
- *             pg_autovacuum definition.       cpp turns this into
- *             typedef struct FormData_pg_autovacuum
- * ----------------
- */
-#define AutovacuumRelationId   1248
-
-CATALOG(pg_autovacuum,1248) BKI_WITHOUT_OIDS
-{
-       Oid                     vacrelid;               /* OID of table */
-       bool            enabled;                /* enabled for this table? */
-       int4            vac_base_thresh;        /* base threshold value */
-       float4          vac_scale_factor;               /* reltuples scaling factor */
-       int4            anl_base_thresh;        /* base threshold value */
-       float4          anl_scale_factor;               /* reltuples scaling factor */
-       int4            vac_cost_delay; /* vacuum cost-based delay */
-       int4            vac_cost_limit; /* vacuum cost limit */
-       int4            freeze_min_age; /* vacuum min freeze age */
-       int4            freeze_max_age; /* max age before forcing vacuum */
-       int4            freeze_table_age; /* age at which vacuum scans whole table */
-} FormData_pg_autovacuum;
-
-/* ----------------
- *             Form_pg_autovacuum corresponds to a pointer to a tuple with
- *             the format of pg_autovacuum relation.
- * ----------------
- */
-typedef FormData_pg_autovacuum *Form_pg_autovacuum;
-
-/* ----------------
- *             compiler constants for pg_autovacuum
- * ----------------
- */
-#define Natts_pg_autovacuum                                                    10
-#define Anum_pg_autovacuum_vacrelid                                    1
-#define Anum_pg_autovacuum_enabled                                     2
-#define Anum_pg_autovacuum_vac_base_thresh                     3
-#define Anum_pg_autovacuum_vac_scale_factor                    4
-#define Anum_pg_autovacuum_anl_base_thresh                     5
-#define Anum_pg_autovacuum_anl_scale_factor                    6
-#define Anum_pg_autovacuum_vac_cost_delay                      7
-#define Anum_pg_autovacuum_vac_cost_limit                      8
-#define Anum_pg_autovacuum_freeze_min_age                      9
-#define Anum_pg_autovacuum_freeze_max_age                      10
-#define Anum_pg_autovacuum_freeze_table_age                    11
-
-/* There are no preloaded tuples in pg_autovacuum.h */
-
-#endif   /* PG_AUTOVACUUM_H */
index ffb2b8530d34a4c8bbde6f51a56066874873c0e9..a3aaf69e2f102c0c2dfd4bed7fbc825e0d82ba7b 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/rel.h,v 1.111 2009/01/01 17:24:02 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/rel.h,v 1.112 2009/02/09 20:57:59 alvherre Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -214,10 +214,26 @@ typedef struct RelationData
  * be applied to relations that use this format or a superset for
  * private options data.
  */
+ /* autovacuum-related reloptions. */
+typedef struct AutoVacOpts
+{
+       bool    enabled;
+       int     vacuum_threshold;
+       int     analyze_threshold;
+       int     vacuum_cost_delay;
+       int     vacuum_cost_limit;
+       int     freeze_min_age;
+       int     freeze_max_age;
+       int             freeze_table_age;
+       float8  vacuum_scale_factor;
+       float8  analyze_scale_factor;
+} AutoVacOpts;
+
 typedef struct StdRdOptions
 {
        int32           vl_len_;                /* varlena header (do not touch directly!) */
        int                     fillfactor;             /* page fill factor in percent (0..100) */
+       AutoVacOpts autovacuum;     /* autovacuum-related options */
 } StdRdOptions;
 
 #define HEAP_MIN_FILLFACTOR                    10
index e677d4580fdcafa85a05165db435bcc3e7a5e92a..c6f1f158ee55cd48471074ac2338a2eff90b7775 100644 (file)
@@ -90,7 +90,6 @@ SELECT relname, relhasindex
  pg_attribute            | t
  pg_auth_members         | t
  pg_authid               | t
- pg_autovacuum           | t
  pg_cast                 | t
  pg_class                | t
  pg_constraint           | t
@@ -152,7 +151,7 @@ SELECT relname, relhasindex
  timetz_tbl              | f
  tinterval_tbl           | f
  varchar_tbl             | f
-(141 rows)
+(140 rows)
 
 --
 -- another sanity check: every system catalog that has OIDs should have