From 6522640d8378b1c8d37631e0cdf44ce4ad394f1f Mon Sep 17 00:00:00 2001
From: Peter Geoghegan <pg@bowt.ie>
Date: Sat, 22 Apr 2023 11:19:50 -0700
Subject: [PATCH v1 4/9] Reorder routine vacuuming sections.

This doesn't change any of the content itself.  It is a mechanical
change.  The new order flows better because it talks about freezing
directly after talking about space recovery tasks.

Old order:

<sect2 id="vacuum-basics">
<sect2 id="vacuum-for-space-recovery">
<sect2 id="vacuum-for-statistics">
<sect2 id="vacuum-for-visibility-map">
<sect2 id="vacuum-for-wraparound">

New order:

<sect2 id="vacuum-basics">
<sect2 id="vacuum-for-space-recovery">
<sect2 id="vacuum-for-wraparound">
<sect2 id="vacuum-for-visibility-map">
<sect2 id="vacuum-for-statistics">

The new order matches processing order inside vacuumlazy.c.  This order
will be easier to work with in two later commits that more or less
rewrite "vacuum-for-wraparound" and "vacuum-for-space-recovery".
(Though it doesn't seem to make the existing content any less meaningful
without the later rewrite commits.)
---
 doc/src/sgml/maintenance.sgml | 306 +++++++++++++++++-----------------
 1 file changed, 155 insertions(+), 151 deletions(-)

diff --git a/doc/src/sgml/maintenance.sgml b/doc/src/sgml/maintenance.sgml
index e8c8647cd..62e22d861 100644
--- a/doc/src/sgml/maintenance.sgml
+++ b/doc/src/sgml/maintenance.sgml
@@ -281,8 +281,9 @@ analyze threshold = analyze base threshold + analyze scale factor * number of tu
      </listitem>
 
      <listitem>
-      <simpara>To update data statistics used by the
-      <productname>PostgreSQL</productname> query planner.</simpara>
+      <simpara>To protect against loss of very old data due to
+      <firstterm>transaction ID wraparound</firstterm> or
+      <firstterm>multixact ID wraparound</firstterm>.</simpara>
      </listitem>
 
      <listitem>
@@ -292,9 +293,8 @@ analyze threshold = analyze base threshold + analyze scale factor * number of tu
      </listitem>
 
      <listitem>
-      <simpara>To protect against loss of very old data due to
-      <firstterm>transaction ID wraparound</firstterm> or
-      <firstterm>multixact ID wraparound</firstterm>.</simpara>
+      <simpara>To update data statistics used by the
+      <productname>PostgreSQL</productname> query planner.</simpara>
      </listitem>
     </orderedlist>
 
@@ -439,151 +439,6 @@ analyze threshold = analyze base threshold + analyze scale factor * number of tu
    </tip>
   </sect2>
 
-  <sect2 id="vacuum-for-statistics">
-   <title>Updating Planner Statistics</title>
-
-   <indexterm zone="vacuum-for-statistics">
-    <primary>statistics</primary>
-    <secondary>of the planner</secondary>
-   </indexterm>
-
-   <indexterm zone="vacuum-for-statistics">
-    <primary>ANALYZE</primary>
-   </indexterm>
-
-   <para>
-    The <productname>PostgreSQL</productname> query planner relies on
-    statistical information about the contents of tables in order to
-    generate good plans for queries.  These statistics are gathered by
-    the <link linkend="sql-analyze"><command>ANALYZE</command></link> command,
-    which can be invoked by itself or
-    as an optional step in <command>VACUUM</command>.  It is important to have
-    reasonably accurate statistics, otherwise poor choices of plans might
-    degrade database performance.
-   </para>
-
-   <para>
-    The autovacuum daemon, if enabled, will automatically issue
-    <command>ANALYZE</command> commands whenever the content of a table has
-    changed sufficiently.  However, administrators might prefer to rely
-    on manually-scheduled <command>ANALYZE</command> operations, particularly
-    if it is known that update activity on a table will not affect the
-    statistics of <quote>interesting</quote> columns.  The daemon schedules
-    <command>ANALYZE</command> strictly as a function of the number of rows
-    inserted or updated; it has no knowledge of whether that will lead
-    to meaningful statistical changes.
-   </para>
-
-   <para>
-    Tuples changed in partitions and inheritance children do not trigger
-    analyze on the parent table.  If the parent table is empty or rarely
-    changed, it may never be processed by autovacuum, and the statistics for
-    the inheritance tree as a whole won't be collected. It is necessary to
-    run <command>ANALYZE</command> on the parent table manually in order to
-    keep the statistics up to date.
-   </para>
-
-   <para>
-    As with vacuuming for space recovery, frequent updates of statistics
-    are more useful for heavily-updated tables than for seldom-updated
-    ones. But even for a heavily-updated table, there might be no need for
-    statistics updates if the statistical distribution of the data is
-    not changing much. A simple rule of thumb is to think about how much
-    the minimum and maximum values of the columns in the table change.
-    For example, a <type>timestamp</type> column that contains the time
-    of row update will have a constantly-increasing maximum value as
-    rows are added and updated; such a column will probably need more
-    frequent statistics updates than, say, a column containing URLs for
-    pages accessed on a website. The URL column might receive changes just
-    as often, but the statistical distribution of its values probably
-    changes relatively slowly.
-   </para>
-
-   <para>
-    It is possible to run <command>ANALYZE</command> on specific tables and even
-    just specific columns of a table, so the flexibility exists to update some
-    statistics more frequently than others if your application requires it.
-    In practice, however, it is usually best to just analyze the entire
-    database, because it is a fast operation.  <command>ANALYZE</command> uses a
-    statistically random sampling of the rows of a table rather than reading
-    every single row.
-   </para>
-
-   <tip>
-    <para>
-     Although per-column tweaking of <command>ANALYZE</command> frequency might not be
-     very productive, you might find it worthwhile to do per-column
-     adjustment of the level of detail of the statistics collected by
-     <command>ANALYZE</command>.  Columns that are heavily used in <literal>WHERE</literal>
-     clauses and have highly irregular data distributions might require a
-     finer-grain data histogram than other columns.  See <command>ALTER TABLE
-     SET STATISTICS</command>, or change the database-wide default using the <xref
-     linkend="guc-default-statistics-target"/> configuration parameter.
-    </para>
-
-    <para>
-     Also, by default there is limited information available about
-     the selectivity of functions.  However, if you create a statistics
-     object or an expression
-     index that uses a function call, useful statistics will be
-     gathered about the function, which can greatly improve query
-     plans that use the expression index.
-    </para>
-   </tip>
-
-   <tip>
-    <para>
-     The autovacuum daemon does not issue <command>ANALYZE</command> commands for
-     foreign tables, since it has no means of determining how often that
-     might be useful.  If your queries require statistics on foreign tables
-     for proper planning, it's a good idea to run manually-managed
-     <command>ANALYZE</command> commands on those tables on a suitable schedule.
-    </para>
-   </tip>
-
-   <tip>
-    <para>
-     The autovacuum daemon does not issue <command>ANALYZE</command> commands
-     for partitioned tables.  Inheritance parents will only be analyzed if the
-     parent itself is changed - changes to child tables do not trigger
-     autoanalyze on the parent table.  If your queries require statistics on
-     parent tables for proper planning, it is necessary to periodically run
-     a manual <command>ANALYZE</command> on those tables to keep the statistics
-     up to date.
-    </para>
-   </tip>
-
-  </sect2>
-
-  <sect2 id="vacuum-for-visibility-map">
-   <title>Updating the Visibility Map</title>
-
-   <para>
-    Vacuum maintains a <link linkend="storage-vm">visibility map</link> for each
-    table to keep track of which pages contain only tuples that are known to be
-    visible to all active transactions (and all future transactions, until the
-    page is again modified).  This has two purposes.  First, vacuum
-    itself can skip such pages on the next run, since there is nothing to
-    clean up.
-   </para>
-
-   <para>
-    Second, it allows <productname>PostgreSQL</productname> to answer some
-    queries using only the index, without reference to the underlying table.
-    Since <productname>PostgreSQL</productname> indexes don't contain tuple
-    visibility information, a normal index scan fetches the heap tuple for each
-    matching index entry, to check whether it should be seen by the current
-    transaction.
-    An <link linkend="indexes-index-only-scans"><firstterm>index-only
-    scan</firstterm></link>, on the other hand, checks the visibility map first.
-    If it's known that all tuples on the page are
-    visible, the heap fetch can be skipped.  This is most useful on
-    large data sets where the visibility map can prevent disk accesses.
-    The visibility map is vastly smaller than the heap, so it can easily be
-    cached even when the heap is very large.
-   </para>
-  </sect2>
-
   <sect2 id="vacuum-for-wraparound">
    <title>Preventing Transaction ID Wraparound Failures</title>
 
@@ -933,7 +788,156 @@ HINT:  Stop the postmaster and vacuum that database in single-user mode.
     </para>
    </sect3>
   </sect2>
- </sect1>
+
+  <sect2 id="vacuum-for-visibility-map">
+   <title>Updating the Visibility Map</title>
+
+   <para>
+    Vacuum maintains a <link linkend="storage-vm">visibility
+     map</link> for each table to keep track of which pages contain
+    only tuples that are known to be visible to all active
+    transactions (and all future transactions, until the page is again
+    modified).  This has two purposes.  First, vacuum itself can skip
+    such pages on the next run, since there is nothing to clean up.
+    Even <command>VACUUM</command>s that use the <link
+     linkend="aggressive-strategy">aggressive strategy</link> can skip
+    pages that are both all-visible and all-frozen (the visibility map
+    keeps track of which pages are all-frozen separately).
+   </para>
+
+   <para>
+    Second, it allows <productname>PostgreSQL</productname> to answer
+    some queries using only the index, without reference to the
+    underlying table.  Since <productname>PostgreSQL</productname>
+    indexes don't contain tuple visibility information, a normal index
+    scan fetches the heap tuple for each matching index entry, to
+    check whether it should be seen by the current transaction.  An
+    <link linkend="indexes-index-only-scans"><firstterm>index-only
+      scan</firstterm></link>, on the other hand, checks the
+    visibility map first.  If it's known that all tuples on the page
+    are visible, the heap fetch can be skipped.  This is most useful
+    on large data sets where the visibility map can prevent disk
+    accesses.  The visibility map is vastly smaller than the heap, so
+    it can easily be cached even when the heap is very large.
+   </para>
+  </sect2>
+
+  <sect2 id="vacuum-for-statistics">
+   <title>Updating Planner Statistics</title>
+
+   <indexterm zone="vacuum-for-statistics">
+    <primary>statistics</primary>
+    <secondary>of the planner</secondary>
+   </indexterm>
+
+   <indexterm zone="vacuum-for-statistics">
+    <primary>ANALYZE</primary>
+   </indexterm>
+
+   <para>
+    The <productname>PostgreSQL</productname> query planner relies on
+    statistical information about the contents of tables in order to
+    generate good plans for queries.  These statistics are gathered by
+    the <link linkend="sql-analyze"><command>ANALYZE</command></link> command,
+    which can be invoked by itself or
+    as an optional step in <command>VACUUM</command>.  It is important to have
+    reasonably accurate statistics, otherwise poor choices of plans might
+    degrade database performance.
+   </para>
+
+   <para>
+    The autovacuum daemon, if enabled, will automatically issue
+    <command>ANALYZE</command> commands whenever the content of a table has
+    changed sufficiently.  However, administrators might prefer to rely
+    on manually-scheduled <command>ANALYZE</command> operations, particularly
+    if it is known that update activity on a table will not affect the
+    statistics of <quote>interesting</quote> columns.  The daemon schedules
+    <command>ANALYZE</command> strictly as a function of the number of rows
+    inserted or updated; it has no knowledge of whether that will lead
+    to meaningful statistical changes.
+   </para>
+
+   <para>
+    Tuples changed in partitions and inheritance children do not trigger
+    analyze on the parent table.  If the parent table is empty or rarely
+    changed, it may never be processed by autovacuum, and the statistics for
+    the inheritance tree as a whole won't be collected. It is necessary to
+    run <command>ANALYZE</command> on the parent table manually in order to
+    keep the statistics up to date.
+   </para>
+
+   <para>
+    As with vacuuming for space recovery, frequent updates of statistics
+    are more useful for heavily-updated tables than for seldom-updated
+    ones. But even for a heavily-updated table, there might be no need for
+    statistics updates if the statistical distribution of the data is
+    not changing much. A simple rule of thumb is to think about how much
+    the minimum and maximum values of the columns in the table change.
+    For example, a <type>timestamp</type> column that contains the time
+    of row update will have a constantly-increasing maximum value as
+    rows are added and updated; such a column will probably need more
+    frequent statistics updates than, say, a column containing URLs for
+    pages accessed on a website. The URL column might receive changes just
+    as often, but the statistical distribution of its values probably
+    changes relatively slowly.
+   </para>
+
+   <para>
+    It is possible to run <command>ANALYZE</command> on specific tables and even
+    just specific columns of a table, so the flexibility exists to update some
+    statistics more frequently than others if your application requires it.
+    In practice, however, it is usually best to just analyze the entire
+    database, because it is a fast operation.  <command>ANALYZE</command> uses a
+    statistically random sampling of the rows of a table rather than reading
+    every single row.
+   </para>
+
+   <tip>
+    <para>
+     Although per-column tweaking of <command>ANALYZE</command> frequency might not be
+     very productive, you might find it worthwhile to do per-column
+     adjustment of the level of detail of the statistics collected by
+     <command>ANALYZE</command>.  Columns that are heavily used in <literal>WHERE</literal>
+     clauses and have highly irregular data distributions might require a
+     finer-grain data histogram than other columns.  See <command>ALTER TABLE
+      SET STATISTICS</command>, or change the database-wide default using the <xref
+      linkend="guc-default-statistics-target"/> configuration parameter.
+    </para>
+
+    <para>
+     Also, by default there is limited information available about
+     the selectivity of functions.  However, if you create a statistics
+     object or an expression
+     index that uses a function call, useful statistics will be
+     gathered about the function, which can greatly improve query
+     plans that use the expression index.
+    </para>
+   </tip>
+
+   <tip>
+    <para>
+     The autovacuum daemon does not issue <command>ANALYZE</command> commands for
+     foreign tables, since it has no means of determining how often that
+     might be useful.  If your queries require statistics on foreign tables
+     for proper planning, it's a good idea to run manually-managed
+     <command>ANALYZE</command> commands on those tables on a suitable schedule.
+    </para>
+   </tip>
+
+   <tip>
+    <para>
+     The autovacuum daemon does not issue <command>ANALYZE</command> commands
+     for partitioned tables.  Inheritance parents will only be analyzed if the
+     parent itself is changed - changes to child tables do not trigger
+     autoanalyze on the parent table.  If your queries require statistics on
+     parent tables for proper planning, it is necessary to periodically run
+     a manual <command>ANALYZE</command> on those tables to keep the statistics
+     up to date.
+    </para>
+   </tip>
+
+  </sect2>
+</sect1>
 
 
  <sect1 id="routine-reindex">
-- 
2.40.0

