C08 — Visibility Map Integrity¶
The visibility map is an internal structure PostgreSQL uses to skip unnecessary work during vacuuming and index-only scans — when it's wrong, both get slower or, in rarer cases, return wrong answers. This category checks for VM/heap mismatches (via pg_visibility, where installed) and the specific advisory state PostgreSQL can leave behind after a crash.
6 checks, PGHF08-001 through PGHF08-006. Every check here is PGHF-namespace and built-in — see Metadata Columns Explained for what each field below actually means, and Resetting to Defaults for why these definitions can't be hand-edited in place.
PGHF08-001 — Heap block reads vs index scans¶
Disproportionately high heap block reads relative to index scans suggests the visibility map is too stale to support index-only scans — the planner has to visit the heap anyway to confirm visibility, wasting the whole point of an index-only plan.
How to fix
VACUUM (not just ANALYZE) is what actually refreshes the visibility map. If this recurs quickly on a high-write table, the table needs more frequent autovacuum — see PGHF05-006's autovacuum_vacuum_scale_factor remediation.
PGHF08-002 — relallvisible consistency¶
relallvisible drifting far out of line with relpages means the catalog's visibility-map statistics are out of sync with the table's actual state — a VACUUM ANALYZE refreshes them, but until then the planner is working from stale numbers.
How to fix
PGHF08-003 — Post-crash visibility map advisory¶
On PostgreSQL versions before 9.6, visibility map pages aren't WAL-logged, so they can be stale immediately after a crash or unclean restart — a reminder to treat VM-derived index-only-scan results with extra suspicion right after recovery.
How to fix
If this server just recovered from a crash and is still on a pre-9.6 version (itself long past end-of-life — see PGHF01-002), run VACUUM cluster-wide to rebuild visibility map state before trusting index-only scan results:
The real fix is upgrading off a version that's been unsupported for years — this advisory is a stopgap, not a destination.
PGHF08-004 — pg_visibility extension¶
Without pg_visibility installed, there's no way to periodically run pg_check_frozen()/pg_check_visible() to catch visibility-map inconsistencies directly — the diagnostic capability PGHF08-006 depends on simply doesn't exist yet.
How to fix
CREATE EXTENSION pg_visibility;
SELECT pghf.seed_data(); -- registers PGHF08-006 now that the extension is present
PGHF08-005 — Dead tuple counter anomaly candidates¶
A high-write table reporting suspiciously few dead tuples despite heavy update/delete activity is a red flag that its statistics were reset (pg_stat_reset()) rather than genuinely clean — worth cross-checking against autovacuum logs before trusting the number.
How to fix
No direct fix — this is a data-quality flag on the statistics, not the table itself. Check pg_stat_user_tables.last_autovacuum/the server log for autovacuum activity around the suspected reset time, and treat any bloat-related check (PGHF05-003/PGHF05-009) on this table with extra scrutiny until stats have accumulated over a full representative period again.
PGHF08-006 — VM integrity (pg_visibility)¶
This is the direct, page-level check for VM/heap mismatches that autovacuum cannot self-heal — a page incorrectly marked all-visible or all-frozen despite containing problematic tuples means index-only scans can silently return wrong results.
How to fix
For a table flagged with actual VM/heap mismatches:
SELECT * FROM pg_check_frozen('schema.the_table'); -- lists specific bad tuples
VACUUM schema.the_table; -- does NOT clear an already-wrong all-visible/all-frozen bit
A genuinely corrupted visibility map bit is not fixed by VACUUM alone — on PG9.6+, pg_visibility provides pg_truncate_visibility_map('schema.the_table') to force a full VM rebuild on the next vacuum, which is the actual repair path here. Treat repeated occurrences on the same table as a signal to also run PGHF07-007/PGHF07-009 for heap-level corruption, not just a VM-layer issue.
Continue to C09 — WAL & Replication Slot Health.