Update autovacuum to use reloptions instead of a system catalog, for

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.
This commit is contained in:
Alvaro Herrera 2009-02-09 20:57:59 +00:00
parent 57b10ebcd4
commit 834a6da4f7
13 changed files with 421 additions and 483 deletions

View 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 Documentation of the system catalogs, directed toward PostgreSQL developers
--> -->
@ -88,11 +88,6 @@
<entry>authorization identifier membership relationships</entry> <entry>authorization identifier membership relationships</entry>
</row> </row>
<row>
<entry><link linkend="catalog-pg-autovacuum"><structname>pg_autovacuum</structname></link></entry>
<entry>per-relation autovacuum configuration parameters</entry>
</row>
<row> <row>
<entry><link linkend="catalog-pg-cast"><structname>pg_cast</structname></link></entry> <entry><link linkend="catalog-pg-cast"><structname>pg_cast</structname></link></entry>
<entry>casts (data type conversions)</entry> <entry>casts (data type conversions)</entry>
@ -1256,178 +1251,6 @@
</sect1> </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"> <sect1 id="catalog-pg-cast">
<title><structname>pg_cast</structname></title> <title><structname>pg_cast</structname></title>

View 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"> <chapter Id="runtime-config">
<title>Server Configuration</title> <title>Server Configuration</title>
@ -3547,8 +3547,8 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;
The default is 50 tuples. The default is 50 tuples.
This parameter can only be set in the <filename>postgresql.conf</> This parameter can only be set in the <filename>postgresql.conf</>
file or on the server command line. file or on the server command line.
This setting can be overridden for individual tables by entries in This setting can be overridden for individual tables by
<structname>pg_autovacuum</>. changing storage parameters.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@ -3565,8 +3565,8 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;
The default is 50 tuples. The default is 50 tuples.
This parameter can only be set in the <filename>postgresql.conf</> This parameter can only be set in the <filename>postgresql.conf</>
file or on the server command line. file or on the server command line.
This setting can be overridden for individual tables by entries in This setting can be overridden for individual tables by
<structname>pg_autovacuum</>. changing storage parameters.
</para> </para>
</listitem> </listitem>
</varlistentry> </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). The default is 0.2 (20% of table size).
This parameter can only be set in the <filename>postgresql.conf</> This parameter can only be set in the <filename>postgresql.conf</>
file or on the server command line. file or on the server command line.
This setting can be overridden for individual tables by entries in This setting can be overridden for individual tables by
<structname>pg_autovacuum</>. changing storage parameters.
</para> </para>
</listitem> </listitem>
</varlistentry> </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). The default is 0.1 (10% of table size).
This parameter can only be set in the <filename>postgresql.conf</> This parameter can only be set in the <filename>postgresql.conf</>
file or on the server command line. file or on the server command line.
This setting can be overridden for individual tables by entries in This setting can be overridden for individual tables by
<structname>pg_autovacuum</>. changing storage parameters.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@ -3624,8 +3624,8 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;
autovacuum is otherwise disabled. autovacuum is otherwise disabled.
The default is 200 million transactions. The default is 200 million transactions.
This parameter can only be set at server start, but the setting This parameter can only be set at server start, but the setting
can be reduced for individual tables by entries in can be reduced for individual tables by
<structname>pg_autovacuum</>. changing storage parameters.
For more information see <xref linkend="vacuum-for-wraparound">. For more information see <xref linkend="vacuum-for-wraparound">.
</para> </para>
</listitem> </listitem>
@ -3645,8 +3645,8 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;
The default value is 20 milliseconds. The default value is 20 milliseconds.
This parameter can only be set in the <filename>postgresql.conf</> This parameter can only be set in the <filename>postgresql.conf</>
file or on the server command line. file or on the server command line.
This setting can be overridden for individual tables by entries in This setting can be overridden for individual tables by
<structname>pg_autovacuum</>. changing storage parameters.
</para> </para>
</listitem> </listitem>
</varlistentry> </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. each worker never exceeds the limit on this variable.
This parameter can only be set in the <filename>postgresql.conf</> This parameter can only be set in the <filename>postgresql.conf</>
file or on the server command line. file or on the server command line.
This setting can be overridden for individual tables by entries in This setting can be overridden for individual tables by
<structname>pg_autovacuum</>. changing storage parameters.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>

View 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"> <chapter id="maintenance">
<title>Routine Database Maintenance Tasks</title> <title>Routine Database Maintenance Tasks</title>
@ -573,7 +573,9 @@ HINT: Stop the postmaster and use a standalone backend to VACUUM in "mydb".
<para> <para>
Tables whose <structfield>relfrozenxid</> value is more than Tables whose <structfield>relfrozenxid</> value is more than
<varname>autovacuum_freeze_max_age</> transactions old are always <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 <command>VACUUM</command> exceeds the <quote>vacuum threshold</quote>, the
table is vacuumed. The vacuum threshold is defined as: table is vacuumed. The vacuum threshold is defined as:
<programlisting> <programlisting>
@ -604,65 +606,39 @@ analyze threshold = analyze base threshold + analyze scale factor * number of tu
<para> <para>
The default thresholds and scale factors are taken from The default thresholds and scale factors are taken from
<filename>postgresql.conf</filename>, but it is possible to override them <filename>postgresql.conf</filename>, but it is possible to override them
on a table-by-table basis by making entries in the system catalog on a table-by-table basis; see
<link <xref linkend="sql-createtable-storage-parameters"
linkend="catalog-pg-autovacuum"><structname>pg_autovacuum</></link>. endterm="sql-createtable-storage-parameters-title"> for more information.
If a <structname>pg_autovacuum</structname> row exists for a particular If a setting
table, the settings it specifies are applied; otherwise the global has been changed via storage parameters, that value is used; otherwise the
settings are used. See <xref linkend="runtime-config-autovacuum"> for global settings are used. See <xref linkend="runtime-config-autovacuum"> for
more details on the global settings. more details on the global settings.
</para> </para>
<para> <para>
Besides the base threshold values and scale factors, there are five Besides the base threshold values and scale factors, there are six
more parameters that can be set for each table in more autovacuum parameters that can be set for each table via
<structname>pg_autovacuum</structname>. storage parameters.
The first, <structname>pg_autovacuum</>.<structfield>enabled</>, The first parameter, <literal>autovacuum_enabled</>,
can be set to <literal>false</literal> to instruct the autovacuum daemon can be set to <literal>false</literal> to instruct the autovacuum daemon
to skip that particular table entirely. In this case to skip that particular table entirely. In this case
autovacuum will only touch the table if it must do so autovacuum will only touch the table if it must do so
to prevent transaction ID wraparound. to prevent transaction ID wraparound.
The next two parameters, the vacuum cost delay Another two parameters,
(<structname>pg_autovacuum</structname>.<structfield>vac_cost_delay</structfield>) <literal>autovacuum_vacuum_cost_delay</literal> and
and the vacuum cost limit <literal>autovacuum_vacuum_cost_limit</literal>, are used to set
(<structname>pg_autovacuum</structname>.<structfield>vac_cost_limit</structfield>), table-specific values for the
are used to set table-specific values for the <xref linkend="runtime-config-resource-vacuum-cost"
<xref linkend="runtime-config-resource-vacuum-cost" endterm="runtime-config-resource-vacuum-cost-title"> endterm="runtime-config-resource-vacuum-cost-title">
feature. feature.
The last two parameters, <literal>autovacuum_freeze_min_age</literal>,
(<structname>pg_autovacuum</structname>.<structfield>freeze_min_age</structfield>) <literal>autovacuum_freeze_max_age</literal> and
and <literal>autovacuum_freeze_table_age</literal> are used to set
(<structname>pg_autovacuum</structname>.<structfield>freeze_max_age</structfield>), values for <xref linkend="guc-vacuum-freeze-min-age">,
are used to set table-specific values for <xref linkend="guc-autovacuum-freeze-max-age"> and
<xref linkend="guc-vacuum-freeze-min-age"> and <xref linkend="guc-vacuum-freeze-table-age"> respectively.
<xref linkend="guc-autovacuum-freeze-max-age"> respectively.
</para> </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> <para>
When multiple workers are running, the cost limit is When multiple workers are running, the cost limit is
<quote>balanced</quote> among all the running workers, so that the <quote>balanced</quote> among all the running workers, so that the

View 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 PostgreSQL documentation
--> -->
@ -286,7 +286,8 @@ where <replaceable class="PARAMETER">action</replaceable> is one of:
<listitem> <listitem>
<para> <para>
This form changes one or more storage parameters for the table. See 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 for details on the available parameters. Note that the table contents
will not be modified immediately by this command; depending on the will not be modified immediately by this command; depending on the
parameter you might need to rewrite the table to get the desired effects. parameter you might need to rewrite the table to get the desired effects.

View 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 PostgreSQL documentation
--> -->
@ -685,19 +685,29 @@ and <replaceable class="PARAMETER">table_constraint</replaceable> is:
<refsect2 id="SQL-CREATETABLE-storage-parameters"> <refsect2 id="SQL-CREATETABLE-storage-parameters">
<title id="SQL-CREATETABLE-storage-parameters-title">Storage Parameters</title> <title id="SQL-CREATETABLE-storage-parameters-title">Storage Parameters</title>
<indexterm zone="sql-createtable-storage-parameters">
<primary>storage parameters</primary>
</indexterm>
<para> <para>
The <literal>WITH</> clause can specify <firstterm>storage parameters</> The <literal>WITH</> clause can specify <firstterm>storage parameters</>
for tables, and for indexes associated with a <literal>UNIQUE</literal> or for tables, and for indexes associated with a <literal>UNIQUE</literal> or
<literal>PRIMARY KEY</literal> constraint. Storage parameters for <literal>PRIMARY KEY</literal> constraint. Storage parameters for
indexes are documented in <xref linkend="SQL-CREATEINDEX" indexes are documented in <xref linkend="SQL-CREATEINDEX"
endterm="sql-createindex-title">. The storage parameters currently 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> </para>
<variablelist> <variablelist>
<varlistentry> <varlistentry>
<term><literal>FILLFACTOR</></term> <term><literal>fillfactor</>, <literal>toast.fillfactor</literal> (<type>integer</>)</term>
<listitem> <listitem>
<para> <para>
The fillfactor for a table is a percentage between 10 and 100. 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>
<varlistentry> <varlistentry>
<term><literal>TOAST.FILLFACTOR</literal></term> <term><literal>autovacuum_enabled</>, <literal>toast.autovacuum_enabled</literal> (<type>boolean</>)</term>
<listitem> <listitem>
<para> <para>
Same as above, for the supplementary storage table, if any; see Enables or disables the autovacuum daemon on a particular table.
<xref linkend="storage-toast">. 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>
Custom <xref linkend="guc-vacuum-freeze-table-age"> parameter.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -48,6 +48,14 @@
static relopt_bool boolRelOpts[] = static relopt_bool boolRelOpts[] =
{ {
{
{
"autovacuum_enabled",
"Enables autovacuum in this relation",
RELOPT_KIND_HEAP
},
true
},
/* list terminator */ /* list terminator */
{ { NULL } } { { NULL } }
}; };
@ -86,12 +94,83 @@ static relopt_int intRelOpts[] =
}, },
GIST_DEFAULT_FILLFACTOR, GIST_MIN_FILLFACTOR, 100 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 */ /* list terminator */
{ { NULL } } { { NULL } }
}; };
static relopt_real realRelOpts[] = 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 */ /* list terminator */
{ { NULL } } { { 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 * bytea *
default_reloptions(Datum reloptions, bool validate, relopt_kind kind) default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
@ -982,7 +1062,27 @@ default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
StdRdOptions *rdopts; StdRdOptions *rdopts;
int numoptions; int numoptions;
relopt_parse_elt tab[] = { 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); options = parseRelOptions(reloptions, validate, kind, &numoptions);

View File

@ -2,7 +2,7 @@
# #
# Makefile for backend/catalog # 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. # indexing.h had better be last, and toasting.h just before it.
POSTGRES_BKI_SRCS = $(addprefix $(top_srcdir)/src/include/catalog/,\ 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_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_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 \ pg_language.h pg_largeobject.h pg_aggregate.h pg_statistic.h \

View File

@ -55,7 +55,7 @@
* *
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -69,12 +69,12 @@
#include "access/genam.h" #include "access/genam.h"
#include "access/heapam.h" #include "access/heapam.h"
#include "access/reloptions.h"
#include "access/transam.h" #include "access/transam.h"
#include "access/xact.h" #include "access/xact.h"
#include "catalog/dependency.h" #include "catalog/dependency.h"
#include "catalog/indexing.h" #include "catalog/indexing.h"
#include "catalog/namespace.h" #include "catalog/namespace.h"
#include "catalog/pg_autovacuum.h"
#include "catalog/pg_database.h" #include "catalog/pg_database.h"
#include "commands/dbcommands.h" #include "commands/dbcommands.h"
#include "commands/vacuum.h" #include "commands/vacuum.h"
@ -165,13 +165,15 @@ typedef struct av_relation
{ {
Oid ar_toastrelid; /* hash key - must be first */ Oid ar_toastrelid; /* hash key - must be first */
Oid ar_relid; Oid ar_relid;
bool ar_hasrelopts;
AutoVacOpts ar_reloptions; /* copy of AutoVacOpts from the main table's
reloptions, or NULL if none */
} av_relation; } av_relation;
/* struct to keep track of tables to vacuum and/or analyze, after rechecking */ /* struct to keep track of tables to vacuum and/or analyze, after rechecking */
typedef struct autovac_table typedef struct autovac_table
{ {
Oid at_relid; Oid at_relid;
Oid at_toastrelid;
bool at_dovacuum; bool at_dovacuum;
bool at_doanalyze; bool at_doanalyze;
int at_freeze_min_age; int at_freeze_min_age;
@ -282,16 +284,17 @@ static void autovac_balance_cost(void);
static void do_autovacuum(void); static void do_autovacuum(void);
static void FreeWorkerInfo(int code, Datum arg); static void FreeWorkerInfo(int code, Datum arg);
static autovac_table *table_recheck_autovac(Oid relid, HTAB *table_toast_map); static autovac_table *table_recheck_autovac(Oid relid, HTAB *table_toast_map,
static void relation_needs_vacanalyze(Oid relid, Form_pg_autovacuum avForm, TupleDesc pg_class_desc);
static void relation_needs_vacanalyze(Oid relid, AutoVacOpts *relopts,
Form_pg_class classForm, Form_pg_class classForm,
PgStat_StatTabEntry *tabentry, bool *dovacuum, PgStat_StatTabEntry *tabentry,
bool *doanalyze, bool *wraparound); bool *dovacuum, bool *doanalyze, bool *wraparound);
static void autovacuum_do_vac_analyze(autovac_table *tab, static void autovacuum_do_vac_analyze(autovac_table *tab,
BufferAccessStrategy bstrategy); BufferAccessStrategy bstrategy);
static HeapTuple get_pg_autovacuum_tuple_relid(Relation avRel, Oid relid, static AutoVacOpts *extract_autovac_opts(HeapTuple tup,
HTAB *table_toast_map); TupleDesc pg_class_desc);
static PgStat_StatTabEntry *get_pgstat_tabentry_relid(Oid relid, bool isshared, static PgStat_StatTabEntry *get_pgstat_tabentry_relid(Oid relid, bool isshared,
PgStat_StatDBEntry *shared, PgStat_StatDBEntry *shared,
PgStat_StatDBEntry *dbentry); PgStat_StatDBEntry *dbentry);
@ -1816,8 +1819,7 @@ get_database_list(void)
static void static void
do_autovacuum(void) do_autovacuum(void)
{ {
Relation classRel, Relation classRel;
avRel;
HeapTuple tuple; HeapTuple tuple;
HeapScanDesc relScan; HeapScanDesc relScan;
Form_pg_database dbForm; Form_pg_database dbForm;
@ -1829,6 +1831,7 @@ do_autovacuum(void)
PgStat_StatDBEntry *dbentry; PgStat_StatDBEntry *dbentry;
BufferAccessStrategy bstrategy; BufferAccessStrategy bstrategy;
ScanKeyData key; ScanKeyData key;
TupleDesc pg_class_desc;
/* /*
* StartTransactionCommand and CommitTransactionCommand will automatically * StartTransactionCommand and CommitTransactionCommand will automatically
@ -1890,12 +1893,14 @@ do_autovacuum(void)
shared = pgstat_fetch_stat_dbentry(InvalidOid); shared = pgstat_fetch_stat_dbentry(InvalidOid);
classRel = heap_open(RelationRelationId, AccessShareLock); 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 */ /* create hash table for toast <-> main relid mapping */
MemSet(&ctl, 0, sizeof(ctl)); MemSet(&ctl, 0, sizeof(ctl));
ctl.keysize = sizeof(Oid); ctl.keysize = sizeof(Oid);
ctl.entrysize = sizeof(Oid) * 2; ctl.entrysize = sizeof(av_relation);
ctl.hash = oid_hash; ctl.hash = oid_hash;
table_toast_map = hash_create("TOAST to main relid map", 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 * 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. * 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 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 * the main relation's pg_class.reloptions entry if the TOAST table does
* any, and we cannot obtain it unless we know beforehand what's the main * not have any, and we cannot obtain it unless we know beforehand what's
* table OID. * the main table OID.
* *
* We need to check TOAST tables separately because in cases with short, * We need to check TOAST tables separately because in cases with short,
* wide tables there might be proportionally much more activity in the * 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) while ((tuple = heap_getnext(relScan, ForwardScanDirection)) != NULL)
{ {
Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple); Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple);
Form_pg_autovacuum avForm = NULL;
PgStat_StatTabEntry *tabentry; PgStat_StatTabEntry *tabentry;
HeapTuple avTup; AutoVacOpts *relopts;
Oid relid; Oid relid;
bool dovacuum; bool dovacuum;
bool doanalyze; bool doanalyze;
@ -1942,17 +1946,13 @@ do_autovacuum(void)
relid = HeapTupleGetOid(tuple); relid = HeapTupleGetOid(tuple);
/* Fetch the pg_autovacuum tuple for the relation, if any */ /* Fetch reloptions and the pgstat entry for this table */
avTup = get_pg_autovacuum_tuple_relid(avRel, relid, NULL); relopts = extract_autovac_opts(tuple, pg_class_desc);
if (HeapTupleIsValid(avTup))
avForm = (Form_pg_autovacuum) GETSTRUCT(avTup);
/* Fetch the pgstat entry for this table */
tabentry = get_pgstat_tabentry_relid(relid, classForm->relisshared, tabentry = get_pgstat_tabentry_relid(relid, classForm->relisshared,
shared, dbentry); shared, dbentry);
/* Check if it needs vacuum or analyze */ /* Check if it needs vacuum or analyze */
relation_needs_vacanalyze(relid, avForm, classForm, tabentry, relation_needs_vacanalyze(relid, relopts, classForm, tabentry,
&dovacuum, &doanalyze, &wraparound); &dovacuum, &doanalyze, &wraparound);
/* /*
@ -1998,7 +1998,7 @@ do_autovacuum(void)
} }
else else
{ {
/* Plain relations that need work are added to table_oids */ /* relations that need work are added to table_oids */
if (dovacuum || doanalyze) if (dovacuum || doanalyze)
table_oids = lappend_oid(table_oids, relid); table_oids = lappend_oid(table_oids, relid);
@ -2020,12 +2020,16 @@ do_autovacuum(void)
{ {
/* hash_search already filled in the key */ /* hash_search already filled in the key */
hentry->ar_relid = relid; 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); heap_endscan(relScan);
@ -2040,10 +2044,9 @@ do_autovacuum(void)
while ((tuple = heap_getnext(relScan, ForwardScanDirection)) != NULL) while ((tuple = heap_getnext(relScan, ForwardScanDirection)) != NULL)
{ {
Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple); Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple);
Form_pg_autovacuum avForm = NULL;
PgStat_StatTabEntry *tabentry; PgStat_StatTabEntry *tabentry;
HeapTuple avTup;
Oid relid; Oid relid;
AutoVacOpts *relopts = NULL;
bool dovacuum; bool dovacuum;
bool doanalyze; bool doanalyze;
bool wraparound; bool wraparound;
@ -2057,17 +2060,26 @@ do_autovacuum(void)
relid = HeapTupleGetOid(tuple); 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)) hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
avForm = (Form_pg_autovacuum) GETSTRUCT(avTup); if (found && hentry->ar_hasrelopts)
relopts = &hentry->ar_reloptions;
}
/* Fetch the pgstat entry for this table */ /* Fetch the pgstat entry for this table */
tabentry = get_pgstat_tabentry_relid(relid, classForm->relisshared, tabentry = get_pgstat_tabentry_relid(relid, classForm->relisshared,
shared, dbentry); shared, dbentry);
relation_needs_vacanalyze(relid, avForm, classForm, tabentry, relation_needs_vacanalyze(relid, relopts, classForm, tabentry,
&dovacuum, &doanalyze, &wraparound); &dovacuum, &doanalyze, &wraparound);
/* ignore analyze for toast tables */ /* ignore analyze for toast tables */
@ -2076,7 +2088,6 @@ do_autovacuum(void)
} }
heap_endscan(relScan); heap_endscan(relScan);
heap_close(avRel, AccessShareLock);
heap_close(classRel, AccessShareLock); heap_close(classRel, AccessShareLock);
/* /*
@ -2163,10 +2174,10 @@ do_autovacuum(void)
* condition is not closed but it is very small. * condition is not closed but it is very small.
*/ */
MemoryContextSwitchTo(AutovacMemCxt); MemoryContextSwitchTo(AutovacMemCxt);
tab = table_recheck_autovac(relid, table_toast_map); tab = table_recheck_autovac(relid, table_toast_map, pg_class_desc);
if (tab == NULL) if (tab == NULL)
{ {
/* someone else vacuumed the table */ /* someone else vacuumed the table, or it went away */
LWLockRelease(AutovacuumScheduleLock); LWLockRelease(AutovacuumScheduleLock);
continue; continue;
} }
@ -2292,49 +2303,29 @@ deleted:
} }
/* /*
* Returns a copy of the pg_autovacuum tuple for the given relid, or NULL if * extract_autovac_opts
* there isn't any. avRel is pg_autovacuum, already open and suitably locked.
* *
* If table_toast_map is not null, use it to find an alternative OID with which * Given a relation's pg_class tuple, return the AutoVacOpts portion of
* to search a pg_autovacuum entry, if the passed relid does not yield one * reloptions, if set; otherwise, return NULL.
* directly.
*/ */
static HeapTuple AutoVacOpts *
get_pg_autovacuum_tuple_relid(Relation avRel, Oid relid, extract_autovac_opts(HeapTuple tup, TupleDesc pg_class_desc)
HTAB *table_toast_map)
{ {
ScanKeyData entry[1]; bytea *relopts;
SysScanDesc avScan; AutoVacOpts *av;
HeapTuple avTup;
ScanKeyInit(&entry[0], Assert(((Form_pg_class) GETSTRUCT(tup))->relkind == RELKIND_RELATION ||
Anum_pg_autovacuum_vacrelid, ((Form_pg_class) GETSTRUCT(tup))->relkind == RELKIND_TOASTVALUE);
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(relid));
avScan = systable_beginscan(avRel, AutovacuumRelidIndexId, true, relopts = extractRelOptions(tup, pg_class_desc, InvalidOid);
SnapshotNow, 1, entry); if (relopts == NULL)
return NULL;
av = palloc(sizeof(AutoVacOpts));
memcpy(av, &(((StdRdOptions *) relopts)->autovacuum), sizeof(AutoVacOpts));
pfree(relopts);
avTup = systable_getnext(avScan); return av;
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);
}
return avTup;
} }
/* /*
@ -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. * Note that the returned autovac_table does not have the name fields set.
*/ */
static autovac_table * 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; Form_pg_class classForm;
HeapTuple classTup; HeapTuple classTup;
HeapTuple avTup;
Relation avRel;
bool dovacuum; bool dovacuum;
bool doanalyze; bool doanalyze;
autovac_table *tab = NULL; autovac_table *tab = NULL;
@ -2384,6 +2373,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map)
PgStat_StatDBEntry *shared; PgStat_StatDBEntry *shared;
PgStat_StatDBEntry *dbentry; PgStat_StatDBEntry *dbentry;
bool wraparound; bool wraparound;
AutoVacOpts *avopts;
/* use fresh stats */ /* use fresh stats */
autovac_refresh_stats(); autovac_refresh_stats();
@ -2399,23 +2389,27 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map)
return NULL; return NULL;
classForm = (Form_pg_class) GETSTRUCT(classTup); classForm = (Form_pg_class) GETSTRUCT(classTup);
/* /*
* Fetch the pg_autovacuum entry, if any. For a toast table, also try the * Get the applicable reloptions. If it is a TOAST table, try to get the
* main rel's pg_autovacuum entry if there isn't one for the TOAST table * main table reloptions if the toast table itself doesn't have.
* itself.
*/ */
avRel = heap_open(AutovacuumRelationId, AccessShareLock); avopts = extract_autovac_opts(classTup, pg_class_desc);
avTup = get_pg_autovacuum_tuple_relid(avRel, relid, if (classForm->relkind == RELKIND_TOASTVALUE &&
classForm->relkind == RELKIND_TOASTVALUE ? table_toast_map : NULL); avopts == NULL && table_toast_map != NULL)
{
av_relation *hentry;
bool found;
if (HeapTupleIsValid(avTup)) hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
avForm = (Form_pg_autovacuum) GETSTRUCT(avTup); if (found && hentry->ar_hasrelopts)
avopts = &hentry->ar_reloptions;
}
/* fetch the pgstat table entry */ /* fetch the pgstat table entry */
tabentry = get_pgstat_tabentry_relid(relid, classForm->relisshared, tabentry = get_pgstat_tabentry_relid(relid, classForm->relisshared,
shared, dbentry); shared, dbentry);
relation_needs_vacanalyze(relid, avForm, classForm, tabentry, relation_needs_vacanalyze(relid, avopts, classForm, tabentry,
&dovacuum, &doanalyze, &wraparound); &dovacuum, &doanalyze, &wraparound);
/* ignore ANALYZE for toast tables */ /* ignore ANALYZE for toast tables */
@ -2431,41 +2425,28 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map)
int vac_cost_delay; int vac_cost_delay;
/* /*
* Calculate the vacuum cost parameters and the minimum freeze age. If * Calculate the vacuum cost parameters and the freeze ages. If there
* there is a tuple in pg_autovacuum, use it; else, use the GUC * are options set in pg_class.reloptions, use them; in the case of a
* defaults. Note that the fields may contain "-1" (or indeed any * toast table, try the main table too. Otherwise use the GUC
* negative value), which means use the GUC defaults for each setting. * defaults, autovacuum's own first and plain vacuum second.
* In cost_limit, the value 0 also means to use the value from
* elsewhere.
*/ */
if (avForm != NULL) if (avopts)
{ {
vac_cost_limit = (avForm->vac_cost_limit > 0) ? vac_cost_delay = avopts->vacuum_cost_delay;
avForm->vac_cost_limit : vac_cost_limit = avopts->vacuum_cost_limit;
((autovacuum_vac_cost_limit > 0) ? freeze_min_age = avopts->freeze_min_age;
autovacuum_vac_cost_limit : VacuumCostLimit); freeze_table_age = avopts->freeze_table_age;
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;
} }
else else
{ {
vac_cost_limit = (autovacuum_vac_cost_limit > 0) ? /* -1 in autovac setting means use plain vacuum_cost_delay */
autovacuum_vac_cost_limit : VacuumCostLimit; vac_cost_delay = autovacuum_vac_cost_delay >= 0 ?
vac_cost_delay = (autovacuum_vac_cost_delay >= 0) ?
autovacuum_vac_cost_delay : VacuumCostDelay; 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_min_age = default_freeze_min_age;
freeze_table_age = default_freeze_table_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; tab->at_datname = NULL;
} }
heap_close(avRel, AccessShareLock);
if (HeapTupleIsValid(avTup))
heap_freetuple(avTup);
heap_freetuple(classTup); heap_freetuple(classTup);
return tab; 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 * Check whether a relation needs to be vacuumed or analyzed; return each into
* "dovacuum" and "doanalyze", respectively. Also return whether the vacuum is * "dovacuum" and "doanalyze", respectively. Also return whether the vacuum is
* being forced because of Xid wraparound. avForm and tabentry can be NULL, * being forced because of Xid wraparound.
* classForm shouldn't. *
* 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 * A table needs to be vacuumed if the number of dead tuples exceeds a
* threshold. This threshold is calculated as * 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 * We also force vacuum if the table's relfrozenxid is more than freeze_max_age
* transactions back. * transactions back.
* *
* A table whose pg_autovacuum.enabled value is false, is automatically * A table whose autovacuum_enabled option is false is
* skipped (unless we have to vacuum it due to freeze_max_age). Thus * automatically skipped (unless we have to vacuum it due to freeze_max_age).
* autovacuum can be disabled for specific tables. Also, when the stats * Thus autovacuum can be disabled for specific tables. Also, when the stats
* collector does not have data about a table, it will be skipped. * 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 * 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. * autovacuum_vacuum_scale_factor GUC variable. Ditto for analyze.
*/ */
static void static void
relation_needs_vacanalyze(Oid relid, relation_needs_vacanalyze(Oid relid,
Form_pg_autovacuum avForm, AutoVacOpts *relopts,
Form_pg_class classForm, Form_pg_class classForm,
PgStat_StatTabEntry *tabentry, PgStat_StatTabEntry *tabentry,
/* output params below */ /* output params below */
@ -2534,9 +2516,10 @@ relation_needs_vacanalyze(Oid relid,
bool *wraparound) bool *wraparound)
{ {
bool force_vacuum; bool force_vacuum;
bool av_enabled;
float4 reltuples; /* pg_class.reltuples */ float4 reltuples; /* pg_class.reltuples */
/* constants from pg_autovacuum or GUC variables */ /* constants from reloptions or GUC variables */
int vac_base_thresh, int vac_base_thresh,
anl_base_thresh; anl_base_thresh;
float4 vac_scale_factor, float4 vac_scale_factor,
@ -2558,36 +2541,28 @@ relation_needs_vacanalyze(Oid relid,
AssertArg(OidIsValid(relid)); AssertArg(OidIsValid(relid));
/* /*
* Determine vacuum/analyze equation parameters. If there is a tuple in * Determine vacuum/analyze equation parameters. We have two possible
* pg_autovacuum, use it; else, use the GUC defaults. Note that the * sources: the passed reloptions (which could be a main table or a toast
* fields may contain "-1" (or indeed any negative value), which means use * table), or the autovacuum GUC variables.
* the GUC defaults for each setting.
*/ */
if (avForm != NULL) if (relopts)
{ {
vac_scale_factor = (avForm->vac_scale_factor >= 0) ? vac_scale_factor = relopts->vacuum_scale_factor;
avForm->vac_scale_factor : autovacuum_vac_scale; vac_base_thresh = relopts->vacuum_threshold;
vac_base_thresh = (avForm->vac_base_thresh >= 0) ? anl_scale_factor = relopts->analyze_scale_factor;
avForm->vac_base_thresh : autovacuum_vac_thresh; anl_base_thresh = relopts->analyze_threshold;
freeze_max_age = Min(relopts->freeze_max_age,
anl_scale_factor = (avForm->anl_scale_factor >= 0) ? autovacuum_freeze_max_age);
avForm->anl_scale_factor : autovacuum_anl_scale; av_enabled = relopts->enabled;
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;
} }
else else
{ {
vac_scale_factor = autovacuum_vac_scale; vac_scale_factor = autovacuum_vac_scale;
vac_base_thresh = autovacuum_vac_thresh; vac_base_thresh = autovacuum_vac_thresh;
anl_scale_factor = autovacuum_anl_scale; anl_scale_factor = autovacuum_anl_scale;
anl_base_thresh = autovacuum_anl_thresh; anl_base_thresh = autovacuum_anl_thresh;
freeze_max_age = autovacuum_freeze_max_age; freeze_max_age = autovacuum_freeze_max_age;
av_enabled = true;
} }
/* Force vacuum if table is at risk of wraparound */ /* Force vacuum if table is at risk of wraparound */
@ -2599,8 +2574,8 @@ relation_needs_vacanalyze(Oid relid,
xidForceLimit)); xidForceLimit));
*wraparound = force_vacuum; *wraparound = force_vacuum;
/* User disabled it in pg_autovacuum? (But ignore if at risk) */ /* User disabled it in pg_class.reloptions? (But ignore if at risk) */
if (avForm && !avForm->enabled && !force_vacuum) if (!force_vacuum && !av_enabled)
{ {
*doanalyze = false; *doanalyze = false;
*dovacuum = false; *dovacuum = false;

View File

@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 */ /* yyyymmddN */
#define CATALOG_VERSION_NO 200902061 #define CATALOG_VERSION_NO 200902091
#endif #endif

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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)); 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 #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)); DECLARE_UNIQUE_INDEX(pg_cast_oid_index, 2660, on pg_cast using btree(oid oid_ops));
#define CastOidIndexId 2660 #define CastOidIndexId 2660
DECLARE_UNIQUE_INDEX(pg_cast_source_target_index, 2661, on pg_cast using btree(castsource oid_ops, casttarget oid_ops)); DECLARE_UNIQUE_INDEX(pg_cast_source_target_index, 2661, on pg_cast using btree(castsource oid_ops, casttarget oid_ops));

View File

@ -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 */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 * be applied to relations that use this format or a superset for
* private options data. * 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 typedef struct StdRdOptions
{ {
int32 vl_len_; /* varlena header (do not touch directly!) */ int32 vl_len_; /* varlena header (do not touch directly!) */
int fillfactor; /* page fill factor in percent (0..100) */ int fillfactor; /* page fill factor in percent (0..100) */
AutoVacOpts autovacuum; /* autovacuum-related options */
} StdRdOptions; } StdRdOptions;
#define HEAP_MIN_FILLFACTOR 10 #define HEAP_MIN_FILLFACTOR 10

View File

@ -90,7 +90,6 @@ SELECT relname, relhasindex
pg_attribute | t pg_attribute | t
pg_auth_members | t pg_auth_members | t
pg_authid | t pg_authid | t
pg_autovacuum | t
pg_cast | t pg_cast | t
pg_class | t pg_class | t
pg_constraint | t pg_constraint | t
@ -152,7 +151,7 @@ SELECT relname, relhasindex
timetz_tbl | f timetz_tbl | f
tinterval_tbl | f tinterval_tbl | f
varchar_tbl | f varchar_tbl | f
(141 rows) (140 rows)
-- --
-- another sanity check: every system catalog that has OIDs should have -- another sanity check: every system catalog that has OIDs should have