The Visibility Map and Index-Only Scans
Keep the visibility map fresh so the planner can serve index-only scans without heap fetches.
Why Index Scans Still Touch the Heap
In PostgreSQL, a normal index scan finds matching rows in the index, but it cannot trust the index alone to know whether each row is visible to your transaction. MVCC stores visibility information (xmin/xmax) only in the heap tuple, not in the index entry.
- So for every index match, the executor must do a heap fetch to check visibility.
- These random heap accesses dominate the cost of an index scan, especially on a large table.
The visibility map (VM) exists to let PostgreSQL skip that heap fetch when it is provably safe, enabling an index-only scan.
What the Visibility Map Stores
The visibility map is a compact bitmap stored alongside each table (in a _vm fork). It holds two bits per heap page:
- all-visible: every tuple on the page is visible to all current and future transactions.
- all-frozen: every tuple on the page is frozen (used to skip pages during anti-wraparound vacuum).
For index-only scans only the all-visible bit matters. If a heap page's all-visible bit is set, the planner knows any tuple it points to on that page is visible, so it can answer from the index entry alone.
All lessons in this course
- Tuple Visibility, xmin, and xmax
- HOT Updates and Heap-Only Tuple Chains
- The Visibility Map and Index-Only Scans
- WAL Generation and Write Amplification