]> granicus.if.org Git - postgresql/commitdiff
vacuumdb: Add option --analyze-in-stages
authorPeter Eisentraut <peter_e@gmx.net>
Tue, 15 Apr 2014 03:15:05 +0000 (23:15 -0400)
committerPeter Eisentraut <peter_e@gmx.net>
Tue, 15 Apr 2014 04:44:25 +0000 (00:44 -0400)
Add vacuumdb option --analyze-in-stages which runs ANALYZE three times
with different configuration settings, adopting the logic from the
analyze_new_cluster.sh script that pg_upgrade generates.  That way,
users of pg_dump/pg_restore can also use that functionality.

Change pg_upgrade to create the script so that it calls vacuumdb instead
of implementing the logic itself.

contrib/pg_upgrade/check.c
doc/src/sgml/ref/vacuumdb.sgml
src/bin/scripts/t/102_vacuumdb_stages.pl [new file with mode: 0644]
src/bin/scripts/vacuumdb.c

index acf8660044d42ae6685353167b27e9873bd25eee..d22b6d38e291da113c796833ec651ed57fbfc7fa 100644 (file)
@@ -565,62 +565,12 @@ create_script_for_cluster_analyze(char **analyze_script_file_name)
                        "--analyze-only" : "--analyze", ECHO_QUOTE);
        fprintf(script, "echo%s\n\n", ECHO_BLANK);
 
-#ifndef WIN32
-       fprintf(script, "sleep 2\n");
-       fprintf(script, "PGOPTIONS='-c default_statistics_target=1 -c vacuum_cost_delay=0'\n");
-       /* only need to export once */
-       fprintf(script, "export PGOPTIONS\n");
-#else
-       fprintf(script, "REM simulate sleep 2\n");
-       fprintf(script, "PING 1.1.1.1 -n 1 -w 2000 > nul\n");
-       fprintf(script, "SET PGOPTIONS=-c default_statistics_target=1 -c vacuum_cost_delay=0\n");
-#endif
-
-       fprintf(script, "echo %sGenerating minimal optimizer statistics (1 target)%s\n",
-                       ECHO_QUOTE, ECHO_QUOTE);
-       fprintf(script, "echo %s--------------------------------------------------%s\n",
-                       ECHO_QUOTE, ECHO_QUOTE);
-       fprintf(script, "\"%s/vacuumdb\" %s--all --analyze-only\n",
-                       new_cluster.bindir, user_specification);
-       fprintf(script, "echo%s\n", ECHO_BLANK);
-       fprintf(script, "echo %sThe server is now available with minimal optimizer statistics.%s\n",
-                       ECHO_QUOTE, ECHO_QUOTE);
-       fprintf(script, "echo %sQuery performance will be optimal once this script completes.%s\n",
-                       ECHO_QUOTE, ECHO_QUOTE);
-       fprintf(script, "echo%s\n\n", ECHO_BLANK);
-
-#ifndef WIN32
-       fprintf(script, "sleep 2\n");
-       fprintf(script, "PGOPTIONS='-c default_statistics_target=10'\n");
-#else
-       fprintf(script, "REM simulate sleep\n");
-       fprintf(script, "PING 1.1.1.1 -n 1 -w 2000 > nul\n");
-       fprintf(script, "SET PGOPTIONS=-c default_statistics_target=10\n");
-#endif
-
-       fprintf(script, "echo %sGenerating medium optimizer statistics (10 targets)%s\n",
-                       ECHO_QUOTE, ECHO_QUOTE);
-       fprintf(script, "echo %s---------------------------------------------------%s\n",
-                       ECHO_QUOTE, ECHO_QUOTE);
-       fprintf(script, "\"%s/vacuumdb\" %s--all --analyze-only\n",
+       fprintf(script, "\"%s/vacuumdb\" %s--all --analyze-in-stages\n",
                        new_cluster.bindir, user_specification);
-       fprintf(script, "echo%s\n\n", ECHO_BLANK);
-
-#ifndef WIN32
-       fprintf(script, "unset PGOPTIONS\n");
-#else
-       fprintf(script, "SET PGOPTIONS\n");
-#endif
-
-       fprintf(script, "echo %sGenerating default (full) optimizer statistics (100 targets?)%s\n",
-                       ECHO_QUOTE, ECHO_QUOTE);
-       fprintf(script, "echo %s-------------------------------------------------------------%s\n",
-                       ECHO_QUOTE, ECHO_QUOTE);
-       fprintf(script, "\"%s/vacuumdb\" %s--all %s\n", new_cluster.bindir,
-                       user_specification,
        /* Did we copy the free space files? */
-                       (GET_MAJOR_VERSION(old_cluster.major_version) >= 804) ?
-                       "--analyze-only" : "--analyze");
+       if (GET_MAJOR_VERSION(old_cluster.major_version) < 804)
+               fprintf(script, "\"%s/vacuumdb\" %s--all\n", new_cluster.bindir,
+                               user_specification);
 
        fprintf(script, "echo%s\n\n", ECHO_BLANK);
        fprintf(script, "echo %sDone%s\n",
index 1c519f5944f60e315c8bf617aaf6434c3d386866..3ecd9999812080e41270540f402f2829227a193d 100644 (file)
@@ -203,6 +203,26 @@ PostgreSQL documentation
       </listitem>
      </varlistentry>
 
+     <varlistentry>
+      <term><option>--analyze-in-stages</option></term>
+      <listitem>
+       <para>
+        Only calculate statistics for use by the optimizer (no vacuum),
+        like <option>--analyze-only</option>.  Run several (currently three)
+        stages of analyze with different configuration settings, to produce
+        usable statistics faster.
+       </para>
+
+       <para>
+        This option is useful to analyze a database that was newly populated
+        from a restored dump or by <command>pg_upgrade</command>.  This option
+        will try to create some statistics as fast as possible, to make the
+        database usable, and then produce full statistics in the subsequent
+        stages.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry>
        <term><option>-?</></term>
        <term><option>--help</></term>
diff --git a/src/bin/scripts/t/102_vacuumdb_stages.pl b/src/bin/scripts/t/102_vacuumdb_stages.pl
new file mode 100644 (file)
index 0000000..743743e
--- /dev/null
@@ -0,0 +1,16 @@
+use strict;
+use warnings;
+use TestLib;
+use Test::More tests => 1;
+
+my $tempdir = tempdir;
+start_test_server $tempdir;
+
+issues_sql_like(['vacuumdb', '--analyze-in-stages', 'postgres'],
+                               qr/.*statement:\ SET\ default_statistics_target=1;\ SET\ vacuum_cost_delay=0;
+                   .*statement:\ ANALYZE.*
+                   .*statement:\ SET\ default_statistics_target=10;\ RESET\ vacuum_cost_delay;
+                   .*statement:\ ANALYZE.*
+                   .*statement:\ RESET\ default_statistics_target;
+                   .*statement:\ ANALYZE/sx,
+                               'analyze three times');
index 07a60d0b6d4db4c5ed90ab17a610158ab8389b22..1e288ef978cec3cb6f6fc0f7dd381c15288ef255 100644 (file)
 
 
 static void vacuum_one_database(const char *dbname, bool full, bool verbose,
-                                       bool and_analyze, bool analyze_only, bool freeze,
+                                       bool and_analyze, bool analyze_only, bool analyze_in_stages, bool freeze,
                                        const char *table, const char *host, const char *port,
                                        const char *username, enum trivalue prompt_password,
                                        const char *progname, bool echo);
 static void vacuum_all_databases(bool full, bool verbose, bool and_analyze,
-                                        bool analyze_only, bool freeze,
+                                        bool analyze_only, bool analyze_in_stages, bool freeze,
                                         const char *maintenance_db,
                                         const char *host, const char *port,
                                         const char *username, enum trivalue prompt_password,
@@ -50,6 +50,7 @@ main(int argc, char *argv[])
                {"full", no_argument, NULL, 'f'},
                {"verbose", no_argument, NULL, 'v'},
                {"maintenance-db", required_argument, NULL, 2},
+               {"analyze-in-stages", no_argument, NULL, 3},
                {NULL, 0, NULL, 0}
        };
 
@@ -67,6 +68,7 @@ main(int argc, char *argv[])
        bool            quiet = false;
        bool            and_analyze = false;
        bool            analyze_only = false;
+       bool            analyze_in_stages = false;
        bool            freeze = false;
        bool            alldb = false;
        bool            full = false;
@@ -130,6 +132,9 @@ main(int argc, char *argv[])
                        case 2:
                                maintenance_db = pg_strdup(optarg);
                                break;
+                       case 3:
+                               analyze_in_stages = analyze_only = true;
+                               break;
                        default:
                                fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
                                exit(1);
@@ -189,7 +194,7 @@ main(int argc, char *argv[])
                        exit(1);
                }
 
-               vacuum_all_databases(full, verbose, and_analyze, analyze_only, freeze,
+               vacuum_all_databases(full, verbose, and_analyze, analyze_only, analyze_in_stages, freeze,
                                                         maintenance_db, host, port, username,
                                                         prompt_password, progname, echo, quiet);
        }
@@ -212,7 +217,7 @@ main(int argc, char *argv[])
                        for (cell = tables.head; cell; cell = cell->next)
                        {
                                vacuum_one_database(dbname, full, verbose, and_analyze,
-                                                                       analyze_only,
+                                                                       analyze_only, analyze_in_stages,
                                                                        freeze, cell->val,
                                                                        host, port, username, prompt_password,
                                                                        progname, echo);
@@ -220,7 +225,7 @@ main(int argc, char *argv[])
                }
                else
                        vacuum_one_database(dbname, full, verbose, and_analyze,
-                                                               analyze_only,
+                                                               analyze_only, analyze_in_stages,
                                                                freeze, NULL,
                                                                host, port, username, prompt_password,
                                                                progname, echo);
@@ -230,9 +235,26 @@ main(int argc, char *argv[])
 }
 
 
+static void
+run_vacuum_command(PGconn *conn, const char *sql, bool echo, const char *dbname, const char *table, const char *progname)
+{
+       if (!executeMaintenanceCommand(conn, sql, echo))
+       {
+               if (table)
+                       fprintf(stderr, _("%s: vacuuming of table \"%s\" in database \"%s\" failed: %s"),
+                                       progname, table, dbname, PQerrorMessage(conn));
+               else
+                       fprintf(stderr, _("%s: vacuuming of database \"%s\" failed: %s"),
+                                       progname, dbname, PQerrorMessage(conn));
+               PQfinish(conn);
+               exit(1);
+       }
+}
+
+
 static void
 vacuum_one_database(const char *dbname, bool full, bool verbose, bool and_analyze,
-                                       bool analyze_only, bool freeze, const char *table,
+                                       bool analyze_only, bool analyze_in_stages, bool freeze, const char *table,
                                        const char *host, const char *port,
                                        const char *username, enum trivalue prompt_password,
                                        const char *progname, bool echo)
@@ -300,17 +322,30 @@ vacuum_one_database(const char *dbname, bool full, bool verbose, bool and_analyz
                appendPQExpBuffer(&sql, " %s", table);
        appendPQExpBufferStr(&sql, ";");
 
-       if (!executeMaintenanceCommand(conn, sql.data, echo))
+       if (analyze_in_stages)
        {
-               if (table)
-                       fprintf(stderr, _("%s: vacuuming of table \"%s\" in database \"%s\" failed: %s"),
-                                       progname, table, dbname, PQerrorMessage(conn));
-               else
-                       fprintf(stderr, _("%s: vacuuming of database \"%s\" failed: %s"),
-                                       progname, dbname, PQerrorMessage(conn));
-               PQfinish(conn);
-               exit(1);
+               const char *stage_commands[] = {
+                       "SET default_statistics_target=1; SET vacuum_cost_delay=0;",
+                       "SET default_statistics_target=10; RESET vacuum_cost_delay;",
+                       "RESET default_statistics_target;"
+               };
+               const char *stage_messages[] = {
+                       gettext_noop("Generating minimal optimizer statistics (1 target)"),
+                       gettext_noop("Generating medium optimizer statistics (10 targets)"),
+                       gettext_noop("Generating default (full) optimizer statistics")
+               };
+               int i;
+
+               for (i = 0; i < 3; i++)
+               {
+                       puts(gettext(stage_messages[i]));
+                       executeCommand(conn, stage_commands[i], progname, echo);
+                       run_vacuum_command(conn, sql.data, echo, dbname, table, progname);
+               }
        }
+       else
+               run_vacuum_command(conn, sql.data, echo, dbname, NULL, progname);
+
        PQfinish(conn);
        termPQExpBuffer(&sql);
 }
@@ -318,7 +353,7 @@ vacuum_one_database(const char *dbname, bool full, bool verbose, bool and_analyz
 
 static void
 vacuum_all_databases(bool full, bool verbose, bool and_analyze, bool analyze_only,
-                                        bool freeze, const char *maintenance_db,
+                                        bool analyze_in_stages, bool freeze, const char *maintenance_db,
                                         const char *host, const char *port,
                                         const char *username, enum trivalue prompt_password,
                                         const char *progname, bool echo, bool quiet)
@@ -343,6 +378,7 @@ vacuum_all_databases(bool full, bool verbose, bool and_analyze, bool analyze_onl
                }
 
                vacuum_one_database(dbname, full, verbose, and_analyze, analyze_only,
+                                                       analyze_in_stages,
                                                 freeze, NULL, host, port, username, prompt_password,
                                                        progname, echo);
        }
@@ -369,6 +405,8 @@ help(const char *progname)
        printf(_("  -V, --version                   output version information, then exit\n"));
        printf(_("  -z, --analyze                   update optimizer statistics\n"));
        printf(_("  -Z, --analyze-only              only update optimizer statistics\n"));
+       printf(_("      --analyze-in-stages         only update optimizer statistics, in multiple\n"
+                        "                                  stages for faster results\n"));
        printf(_("  -?, --help                      show this help, then exit\n"));
        printf(_("\nConnection options:\n"));
        printf(_("  -h, --host=HOSTNAME       database server host or socket directory\n"));