Avoid per-object queries in performance-critical paths in pg_dump.

Instead of issuing a secondary data-collection query against each
table to be dumped, issue just one query, with a WHERE clause
restricting it to be applied to only the tables we intend to dump.
Likewise for indexes, constraints, and triggers.  This greatly
reduces the number of queries needed to dump a database containing
many tables.  It might seem that WHERE clauses listing many target
OIDs could be inefficient, but at least on recent server versions
this provides a very substantial speedup.

(In principle the same thing could be done with other object types
such as functions; but that would require significant refactoring
of pg_dump, so those will be tackled in a different way in a
following patch.)

The new WHERE clauses depend on the unnest() function, which is
only present in 8.4 and above.  We could implement them differently
for older servers, but there is an ongoing discussion that will
probably result in dropping pg_dump support for servers before 9.2,
so that seems like it'd be wasted work.  For now, just bump the
server version check to require >= 8.4, without stopping to remove
any of the code that's thereby rendered dead.  We'll mop that
situation up soon.

Patch by me, based on an idea from Andres Freund.

Discussion: https://postgr.es/m/7d7eb6128f40401d81b3b7a898b6b4de@W2012-02.nidsa.loc
This commit is contained in:
Tom Lane 2021-12-06 13:07:31 -05:00
parent e3fcbbd623
commit 9895961529
2 changed files with 1033 additions and 785 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1775,11 +1775,11 @@ connectDatabase(const char *dbname, const char *connection_string,
my_version = PG_VERSION_NUM; my_version = PG_VERSION_NUM;
/* /*
* We allow the server to be back to 8.0, and up to any minor release of * We allow the server to be back to 8.4, and up to any minor release of
* our own major version. (See also version check in pg_dump.c.) * our own major version. (See also version check in pg_dump.c.)
*/ */
if (my_version != server_version if (my_version != server_version
&& (server_version < 80000 || && (server_version < 80400 ||
(server_version / 100) > (my_version / 100))) (server_version / 100) > (my_version / 100)))
{ {
pg_log_error("server version: %s; %s version: %s", pg_log_error("server version: %s; %s version: %s",