postgres.git / summary / log / commit / refs

commit    5d6eac80cdce7aa7c5f4ec74208ddc1feea9eef3
Author:   Nathan Bossart <nathan@postgresql.org>
Date:     Thu May 22 15:23:26 2025 +0000
First released in: 18.0

    pg_dump: Adjust reltuples from 0 to -1 for dumps of older versions.
    
    Before v14, a reltuples value of 0 was ambiguous: it could either
    mean the relation is empty, or it could mean that it hadn't yet
    been vacuumed or analyzed.  (Commit 3d351d916b taught v14 and newer
    to use -1 for the latter case.)  This ambiguity allegedly can cause
    the planner to choose inefficient plans after restoring to v18 or
    newer.  To fix, let's just dump reltuples as -1 in that case.  This
    will cause some truly empty tables to be seen as not-yet-processed,
    but that seems unlikely to cause too much trouble in practice.
    
    Note that we could alternatively teach pg_restore_relation_stats()
    to translate reltuples based on the version argument, but since
    that function doesn't exist until v18, there's no particular
    advantage to that approach.  That is, there's no chance of
    restoring stats dumped from a pre-v14 server to another pre-v14
    server.  Per discussion, the current policy is to fix pre-v18
    behavior differences during export and everything else during
    import.
    
    Commit 9879105024 fixed a similar problem for vacuumdb by removing
    the check for reltuples != 0.  Presumably we could reinstate that
    check now, but I've chosen to leave it in place in case reltuples
    isn't accurate.  As before, processing some empty tables seems
    relatively harmless.
    
    Author: Hari Krishna Sunder <hari.db.pg@gmail.com>
    Reviewed-by: Jeff Davis <pgsql@j-davis.com>
    Reviewed-by: Corey Huinker <corey.huinker@gmail.com>
    Discussion: https://postgr.es/m/CAAeiqZ0o2p4SX5_xPcuAbbsmXjg6MJLNuPYSLUjC%3DWh-VeW64A%40mail.gmail.com


src/bin/pg_dump/pg_dump.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index c73e73a87d1..37432e66efd 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -10929,7 +10929,20 @@ dumpRelationStats_dumper(Archive *fout, const void *userArg, const TocEntry *te) appendStringLiteralAH(out, rsinfo->dobj.name, fout); appendPQExpBufferStr(out, ",\n"); appendPQExpBuffer(out, "\t'relpages', '%d'::integer,\n", rsinfo->relpages); - appendPQExpBuffer(out, "\t'reltuples', '%s'::real,\n", rsinfo->reltuples); + + /* + * Before v14, a reltuples value of 0 was ambiguous: it could either mean + * the relation is empty, or it could mean that it hadn't yet been + * vacuumed or analyzed. (Newer versions use -1 for the latter case.) + * This ambiguity allegedly can cause the planner to choose inefficient + * plans after restoring to v18 or newer. To deal with this, let's just + * set reltuples to -1 in that case. + */ + if (fout->remoteVersion < 140000 && strcmp("0", rsinfo->reltuples) == 0) + appendPQExpBufferStr(out, "\t'reltuples', '-1'::real,\n"); + else + appendPQExpBuffer(out, "\t'reltuples', '%s'::real,\n", rsinfo->reltuples); + appendPQExpBuffer(out, "\t'relallvisible', '%d'::integer", rsinfo->relallvisible); [parent: 1722d5eb05d8]