mirror of
https://github.com/postgres/postgres.git
synced 2025-07-05 07:21:24 +03:00
vacuumdb: Add option --analyze-in-stages
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.
This commit is contained in:
@ -565,62 +565,12 @@ create_script_for_cluster_analyze(char **analyze_script_file_name)
|
|||||||
"--analyze-only" : "--analyze", ECHO_QUOTE);
|
"--analyze-only" : "--analyze", ECHO_QUOTE);
|
||||||
fprintf(script, "echo%s\n\n", ECHO_BLANK);
|
fprintf(script, "echo%s\n\n", ECHO_BLANK);
|
||||||
|
|
||||||
#ifndef WIN32
|
fprintf(script, "\"%s/vacuumdb\" %s--all --analyze-in-stages\n",
|
||||||
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);
|
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",
|
|
||||||
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? */
|
/* Did we copy the free space files? */
|
||||||
(GET_MAJOR_VERSION(old_cluster.major_version) >= 804) ?
|
if (GET_MAJOR_VERSION(old_cluster.major_version) < 804)
|
||||||
"--analyze-only" : "--analyze");
|
fprintf(script, "\"%s/vacuumdb\" %s--all\n", new_cluster.bindir,
|
||||||
|
user_specification);
|
||||||
|
|
||||||
fprintf(script, "echo%s\n\n", ECHO_BLANK);
|
fprintf(script, "echo%s\n\n", ECHO_BLANK);
|
||||||
fprintf(script, "echo %sDone%s\n",
|
fprintf(script, "echo %sDone%s\n",
|
||||||
|
@ -203,6 +203,26 @@ PostgreSQL documentation
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</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>
|
<varlistentry>
|
||||||
<term><option>-?</></term>
|
<term><option>-?</></term>
|
||||||
<term><option>--help</></term>
|
<term><option>--help</></term>
|
||||||
|
16
src/bin/scripts/t/102_vacuumdb_stages.pl
Normal file
16
src/bin/scripts/t/102_vacuumdb_stages.pl
Normal file
@ -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');
|
@ -16,12 +16,12 @@
|
|||||||
|
|
||||||
|
|
||||||
static void vacuum_one_database(const char *dbname, bool full, bool verbose,
|
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 *table, const char *host, const char *port,
|
||||||
const char *username, enum trivalue prompt_password,
|
const char *username, enum trivalue prompt_password,
|
||||||
const char *progname, bool echo);
|
const char *progname, bool echo);
|
||||||
static void vacuum_all_databases(bool full, bool verbose, bool and_analyze,
|
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 *maintenance_db,
|
||||||
const char *host, const char *port,
|
const char *host, const char *port,
|
||||||
const char *username, enum trivalue prompt_password,
|
const char *username, enum trivalue prompt_password,
|
||||||
@ -50,6 +50,7 @@ main(int argc, char *argv[])
|
|||||||
{"full", no_argument, NULL, 'f'},
|
{"full", no_argument, NULL, 'f'},
|
||||||
{"verbose", no_argument, NULL, 'v'},
|
{"verbose", no_argument, NULL, 'v'},
|
||||||
{"maintenance-db", required_argument, NULL, 2},
|
{"maintenance-db", required_argument, NULL, 2},
|
||||||
|
{"analyze-in-stages", no_argument, NULL, 3},
|
||||||
{NULL, 0, NULL, 0}
|
{NULL, 0, NULL, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -67,6 +68,7 @@ main(int argc, char *argv[])
|
|||||||
bool quiet = false;
|
bool quiet = false;
|
||||||
bool and_analyze = false;
|
bool and_analyze = false;
|
||||||
bool analyze_only = false;
|
bool analyze_only = false;
|
||||||
|
bool analyze_in_stages = false;
|
||||||
bool freeze = false;
|
bool freeze = false;
|
||||||
bool alldb = false;
|
bool alldb = false;
|
||||||
bool full = false;
|
bool full = false;
|
||||||
@ -130,6 +132,9 @@ main(int argc, char *argv[])
|
|||||||
case 2:
|
case 2:
|
||||||
maintenance_db = pg_strdup(optarg);
|
maintenance_db = pg_strdup(optarg);
|
||||||
break;
|
break;
|
||||||
|
case 3:
|
||||||
|
analyze_in_stages = analyze_only = true;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
|
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -189,7 +194,7 @@ main(int argc, char *argv[])
|
|||||||
exit(1);
|
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,
|
maintenance_db, host, port, username,
|
||||||
prompt_password, progname, echo, quiet);
|
prompt_password, progname, echo, quiet);
|
||||||
}
|
}
|
||||||
@ -212,7 +217,7 @@ main(int argc, char *argv[])
|
|||||||
for (cell = tables.head; cell; cell = cell->next)
|
for (cell = tables.head; cell; cell = cell->next)
|
||||||
{
|
{
|
||||||
vacuum_one_database(dbname, full, verbose, and_analyze,
|
vacuum_one_database(dbname, full, verbose, and_analyze,
|
||||||
analyze_only,
|
analyze_only, analyze_in_stages,
|
||||||
freeze, cell->val,
|
freeze, cell->val,
|
||||||
host, port, username, prompt_password,
|
host, port, username, prompt_password,
|
||||||
progname, echo);
|
progname, echo);
|
||||||
@ -220,7 +225,7 @@ main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
vacuum_one_database(dbname, full, verbose, and_analyze,
|
vacuum_one_database(dbname, full, verbose, and_analyze,
|
||||||
analyze_only,
|
analyze_only, analyze_in_stages,
|
||||||
freeze, NULL,
|
freeze, NULL,
|
||||||
host, port, username, prompt_password,
|
host, port, username, prompt_password,
|
||||||
progname, echo);
|
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
|
static void
|
||||||
vacuum_one_database(const char *dbname, bool full, bool verbose, bool and_analyze,
|
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 *host, const char *port,
|
||||||
const char *username, enum trivalue prompt_password,
|
const char *username, enum trivalue prompt_password,
|
||||||
const char *progname, bool echo)
|
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);
|
appendPQExpBuffer(&sql, " %s", table);
|
||||||
appendPQExpBufferStr(&sql, ";");
|
appendPQExpBufferStr(&sql, ";");
|
||||||
|
|
||||||
if (!executeMaintenanceCommand(conn, sql.data, echo))
|
if (analyze_in_stages)
|
||||||
{
|
{
|
||||||
if (table)
|
const char *stage_commands[] = {
|
||||||
fprintf(stderr, _("%s: vacuuming of table \"%s\" in database \"%s\" failed: %s"),
|
"SET default_statistics_target=1; SET vacuum_cost_delay=0;",
|
||||||
progname, table, dbname, PQerrorMessage(conn));
|
"SET default_statistics_target=10; RESET vacuum_cost_delay;",
|
||||||
else
|
"RESET default_statistics_target;"
|
||||||
fprintf(stderr, _("%s: vacuuming of database \"%s\" failed: %s"),
|
};
|
||||||
progname, dbname, PQerrorMessage(conn));
|
const char *stage_messages[] = {
|
||||||
PQfinish(conn);
|
gettext_noop("Generating minimal optimizer statistics (1 target)"),
|
||||||
exit(1);
|
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);
|
PQfinish(conn);
|
||||||
termPQExpBuffer(&sql);
|
termPQExpBuffer(&sql);
|
||||||
}
|
}
|
||||||
@ -318,7 +353,7 @@ vacuum_one_database(const char *dbname, bool full, bool verbose, bool and_analyz
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
vacuum_all_databases(bool full, bool verbose, bool and_analyze, bool analyze_only,
|
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 *host, const char *port,
|
||||||
const char *username, enum trivalue prompt_password,
|
const char *username, enum trivalue prompt_password,
|
||||||
const char *progname, bool echo, bool quiet)
|
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,
|
vacuum_one_database(dbname, full, verbose, and_analyze, analyze_only,
|
||||||
|
analyze_in_stages,
|
||||||
freeze, NULL, host, port, username, prompt_password,
|
freeze, NULL, host, port, username, prompt_password,
|
||||||
progname, echo);
|
progname, echo);
|
||||||
}
|
}
|
||||||
@ -369,6 +405,8 @@ help(const char *progname)
|
|||||||
printf(_(" -V, --version output version information, then exit\n"));
|
printf(_(" -V, --version output version information, then exit\n"));
|
||||||
printf(_(" -z, --analyze update optimizer statistics\n"));
|
printf(_(" -z, --analyze update optimizer statistics\n"));
|
||||||
printf(_(" -Z, --analyze-only only 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(_(" -?, --help show this help, then exit\n"));
|
||||||
printf(_("\nConnection options:\n"));
|
printf(_("\nConnection options:\n"));
|
||||||
printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
|
printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
|
||||||
|
Reference in New Issue
Block a user