Part of #2530.
The gap
We collect autovacuum lag (PgAutovacuumStatsCollector), wraparound risk (PgWraparoundStatsCollector) and the xmin horizon (PgXminHorizonCollector) — the entire cause chain for bloat — and nothing that measures the damage. A user can watch vacuum fall behind and has no way to see what it has cost them, which is the question they ask immediately afterwards.
The measurement decision, which is the substance
pgstattuple is the canonical answer and gives exact live/dead tuple counts and free space. It performs a full relation scan, so on a large table it is far too expensive to run on a collection cadence. It is also an extension, so availability on managed PostgreSQL has to be checked rather than assumed.
- Estimate queries (the well-known
pg_class.reltuples / relpages versus expected-size calculations) are cheap enough to run regularly and are approximate — they can be badly wrong on tables with unusual column widths or after a schema change.
pgstattuple_approx sits between the two.
Picking one is the work. My inclination is the estimate on cadence with pgstattuple available on demand for a single table, so the routine path is cheap and the precise answer is reachable when someone is actually investigating — but that should be decided against a measurement on a real table, not on reasoning.
Note
Whatever ships must not present an estimate as though it were exact. A bloat number that is quietly ±40% will be used to justify a VACUUM FULL on a production table, and the difference between "estimated" and "measured" needs to survive into the read's payload rather than living only in a doc.
Source: PostgreSQL Wiki — Monitoring (names pgstattuple as the bloat tool).
Part of #2530.
The gap
We collect autovacuum lag (
PgAutovacuumStatsCollector), wraparound risk (PgWraparoundStatsCollector) and the xmin horizon (PgXminHorizonCollector) — the entire cause chain for bloat — and nothing that measures the damage. A user can watch vacuum fall behind and has no way to see what it has cost them, which is the question they ask immediately afterwards.The measurement decision, which is the substance
pgstattupleis the canonical answer and gives exact live/dead tuple counts and free space. It performs a full relation scan, so on a large table it is far too expensive to run on a collection cadence. It is also an extension, so availability on managed PostgreSQL has to be checked rather than assumed.pg_class.reltuples/relpagesversus expected-size calculations) are cheap enough to run regularly and are approximate — they can be badly wrong on tables with unusual column widths or after a schema change.pgstattuple_approxsits between the two.Picking one is the work. My inclination is the estimate on cadence with
pgstattupleavailable on demand for a single table, so the routine path is cheap and the precise answer is reachable when someone is actually investigating — but that should be decided against a measurement on a real table, not on reasoning.Note
Whatever ships must not present an estimate as though it were exact. A bloat number that is quietly ±40% will be used to justify a
VACUUM FULLon a production table, and the difference between "estimated" and "measured" needs to survive into the read's payload rather than living only in a doc.Source: PostgreSQL Wiki — Monitoring (names
pgstattupleas the bloat tool).