Re: Statistics Import and Export
Corey Huinker <corey.huinker@gmail.com>
Commits
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
Change pg_dump default for statistics export.
- 34eb2a80d5a3 18.0 landed
-
pg_dump: Adjust reltuples from 0 to -1 for dumps of older versions.
- 5d6eac80cdce 18.0 landed
-
vacuumdb: Don't skip empty relations in --missing-stats-only mode.
- 987910502420 18.0 cited
-
pg_dump: Fix query for gathering attribute stats on older versions.
- f0d0083f52f9 18.0 landed
-
Prevent redeclaration of typedef TocEntry.
- 8ec0aaeae094 18.0 cited
-
Remove unused function parameters in pg_backup_archiver.c.
- ff3a7f0b6860 18.0 landed
-
pg_dump: Retrieve attribute statistics in batches.
- 9c02e3a986da 18.0 landed
-
pg_dump: Reduce memory usage of dumps with statistics.
- 7d5c83b4e90c 18.0 landed
-
Skip second WriteToc() call for custom-format dumps without data.
- e3cc039a7d93 18.0 landed
-
Add relallfrozen to pg_dump statistics.
- 4694aedf63bf 18.0 landed
-
Matview statistics depend on matview data.
- a0a4601765b8 18.0 cited
-
Add pg_dump --with-{schema|data|statistics} options.
- bde2fb797aae 18.0 landed
-
Stats: use schemaname/relname instead of regclass.
- 650ab8aaf195 18.0 landed
-
CREATE INDEX: do update index stats if autovacuum=off.
- 29d6808edebb 18.0 landed
-
Don't convert to and from floats in pg_dump.
- 1852aea3f526 18.0 landed
-
CREATE INDEX: don't update table stats if autovacuum=off.
- d611f8b1587b 18.0 landed
-
Organize and deduplicate statistics import tests.
- 1d33de9d6837 18.0 landed
-
Address stats export review comments.
- f9f4b43b8dc0 18.0 landed
-
Address stats import review comments.
- 298944e8d802 18.0 landed
-
Add relallfrozen to pg_class
- 99f8f3fbbc8f 18.0 cited
-
Fix pg_strtof() to not crash on NULL endptr.
- ebe919e95336 13.21 landed
- d69c781084f5 17.5 landed
- c7303f01c574 15.13 landed
- 76fbb38ef69c 14.18 landed
- 5c64ece8aaf3 16.9 landed
- 00d61a08c5fa 18.0 landed
-
Use attnum to identify index columns in pg_restore_attribute_stats().
- 40e27d04b4f6 18.0 landed
-
pg_dump: prepare attribute stats query.
- 6ee3b91bad26 18.0 landed
-
Avoid unnecessary relation stats query in pg_dump.
- 8f427187db78 18.0 landed
-
Remove redundant pg_set_*_stats() variants.
- a5cbdeb98af9 18.0 landed
-
Do not use in-place updates for statistics import.
- f3dae2ae5856 18.0 landed
-
Fix confusion about data type of pg_class.relpages and relallvisible.
- 9de2cc455eb9 18.0 landed
-
Documentation fixups for dumping statistics.
- cb45dc3afb05 18.0 landed
-
Trial fix for old cross-version upgrades.
- ab84d0ff806d 18.0 landed
-
Transfer statistics during pg_upgrade.
- 1fd1bd871012 18.0 landed
-
Lock table in ShareUpdateExclusive when importing index stats.
- 9f12da78d953 18.0 landed
-
Use in-place updates for pg_restore_relation_stats().
- a43567483c61 18.0 landed
-
Improve error message for replication of generated columns.
- 8fcd80258bcf 18.0 cited
-
pg_dump: Add dumpSchema and dumpData derivative flags.
- 96a81c1be929 18.0 landed
-
Disallow modifying statistics on system columns.
- 869ee4f10eca 18.0 landed
-
Add missing CommandCounterIncrement() in stats import functions.
- f22e436bff77 18.0 landed
-
Add functions pg_restore_relation_stats(), pg_restore_attribute_stats().
- d32d1463995c 18.0 landed
-
Documentation fixup.
- 07d00692c8da 18.0 landed
-
Add functions pg_set_attribute_stats() and pg_clear_attribute_stats().
- ce207d2a7901 18.0 landed
-
Change pg_*_relation_stats() functions to return type to void.
- dbe6bd4343d8 18.0 landed
-
Disable autovacuum for tables in stats import tests.
- 779972e534c0 18.0 landed
-
Allow pg_set_relation_stats() to set relpages to -1.
- b391d882ff38 18.0 landed
-
Fixup for pg_set_relation_stats().
- 35a015a60045 18.0 landed
-
Create functions pg_set_relation_stats, pg_clear_relation_stats.
- e839c8ecc935 18.0 landed
-
Add memory/disk usage for Window aggregate nodes in EXPLAIN.
- 95d6e9af07d2 18.0 cited
-
Improve performance of dumpSequenceData().
- bd15b7db489d 18.0 cited
-
Add INJECTION_POINT_CACHED() to run injection points directly from cache
- a0a5869a8598 18.0 cited
-
Improve performance of binary_upgrade_set_pg_class_oids().
- 2329cad1b93f 18.0 cited
-
Improve assertion in mdwritev()
- f04d1c1db011 17.0 cited
-
CREATE INDEX: do not update stats during binary upgrade.
- 71b66171d045 17.0 landed
-
Redefine pg_class.reltuples to be -1 before the first VACUUM or ANALYZE.
- 3d351d916b20 14.0 cited
>
> Perhaps it's just me ... but it doesn't seem like it's all that many
>
parameters.
>
It's more than I can memorize, so that feels like a lot to me. Clearly it's
not insurmountable.
> > I am a bit concerned about the number of locks on pg_statistic and the
> > relation itself, doing CatalogOpenIndexes/CatalogCloseIndexes once per
> > attribute rather than once per relation. But I also see that this will
> > mostly get used at a time when no other traffic is on the machine, and
> > whatever it costs, it's still faster than the smallest table sample
> (insert
> > joke about "don't have to be faster than the bear" here).
>
> I continue to not be too concerned about this until and unless it's
> actually shown to be an issue. Keeping things simple and
> straight-forward has its own value.
>
Ok, I'm sold on that plan.
>
> > +/*
> > + * Set statistics for a given pg_class entry.
> > + *
> > + * pg_set_relation_stats(relation Oid, reltuples double, relpages int)
> > + *
> > + * This does an in-place (i.e. non-transactional) update of pg_class,
> just as
> > + * is done in ANALYZE.
> > + *
> > + */
> > +Datum
> > +pg_set_relation_stats(PG_FUNCTION_ARGS)
> > +{
> > + const char *param_names[] = {
> > + "relation",
> > + "reltuples",
> > + "relpages",
> > + };
> > +
> > + Oid relid;
> > + Relation rel;
> > + HeapTuple ctup;
> > + Form_pg_class pgcform;
> > +
> > + for (int i = 0; i <= 2; i++)
> > + if (PG_ARGISNULL(i))
> > + ereport(ERROR,
> > +
> (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
> > + errmsg("%s cannot be NULL",
> param_names[i])));
>
> Why not just mark this function as strict..? Or perhaps we should allow
> NULLs to be passed in and just not update the current value in that
> case?
Strict could definitely apply here, and I'm inclined to make it so.
> Also, in some cases we allow the function to be called with a
> NULL but then make it a no-op rather than throwing an ERROR (eg, if the
> OID ends up being NULL).
Thoughts on it emitting a WARN or NOTICE before returning false?
> Not sure if that makes sense here or not
> offhand but figured I'd mention it as something to consider.
>
> > + pgcform = (Form_pg_class) GETSTRUCT(ctup);
> > + pgcform->reltuples = PG_GETARG_FLOAT4(1);
> > + pgcform->relpages = PG_GETARG_INT32(2);
>
> Shouldn't we include relallvisible?
>
Yes. No idea why I didn't have that in there from the start.
> Also, perhaps we should use the approach that we have in ANALYZE, and
> only actually do something if the values are different rather than just
> always doing an update.
>
That was how it worked back in v1, more for the possibility that there was
no matching JSON to set values.
Looking again at analyze.c (currently lines 1751-1780), we just check if
there is a row in the way, and if so we replace it. I don't see where we
compare existing values to new values.
>
> > +/*
> > + * Import statistics for a given relation attribute
> > + *
> > + * pg_set_attribute_stats(relation Oid, attname name, stainherit bool,
> > + * stanullfrac float4, stawidth int, stadistinct
> float4,
> > + * stakind1 int2, stakind2 int2, stakind3 int3,
> > + * stakind4 int2, stakind5 int2, stanumbers1
> float4[],
> > + * stanumbers2 float4[], stanumbers3 float4[],
> > + * stanumbers4 float4[], stanumbers5 float4[],
> > + * stanumbers1 float4[], stanumbers2 float4[],
> > + * stanumbers3 float4[], stanumbers4 float4[],
> > + * stanumbers5 float4[], stavalues1 text,
> > + * stavalues2 text, stavalues3 text,
> > + * stavalues4 text, stavalues5 text);
> > + *
> > + *
> > + */
>
> Don't know that it makes sense to just repeat the function declaration
> inside a comment like this- it'll just end up out of date.
>
Historical artifact - previous versions had a long explanation of the JSON
format.
>
> > +Datum
> > +pg_set_attribute_stats(PG_FUNCTION_ARGS)
>
> > + /* names of columns that cannot be null */
> > + const char *required_param_names[] = {
> > + "relation",
> > + "attname",
> > + "stainherit",
> > + "stanullfrac",
> > + "stawidth",
> > + "stadistinct",
> > + "stakind1",
> > + "stakind2",
> > + "stakind3",
> > + "stakind4",
> > + "stakind5",
> > + };
>
> Same comment here as above wrt NULL being passed in.
>
In this case, the last 10 params (stanumbersN and stavaluesN) can be null,
and are NULL more often than not.
>
> > + for (int k = 0; k < 5; k++)
>
> Shouldn't we use STATISTIC_NUM_SLOTS here?
>
Yes, I had in the past. Not sure why I didn't again.