Using VACUUM and ANALYZE
1. Understanding VACUUM
| Job | Effect |
|---|---|
| Reclaim dead tuples | Mark space reusable |
| Update visibility map | Enables index-only scans |
| Freeze old tuples | Prevent XID wraparound |
| Update stats | With ANALYZE |
2. Running VACUUM on Table
VACUUM (VERBOSE, ANALYZE) orders;
3. Running VACUUM on Database
VACUUM; -- whole DB
VACUUM ANALYZE;
4. Using VACUUM FULL
VACUUM FULL orders;
Warning: Takes ACCESS EXCLUSIVE lock and rewrites the table. Blocks all queries. Use pg_repack for online alternative.
5. Using VACUUM FREEZE
VACUUM FREEZE orders; -- preemptively freezes all visible tuples
6. Using VACUUM ANALYZE
VACUUM ANALYZE orders; -- reclaim + update planner stats
7. Running ANALYZE on Table
ANALYZE orders;
8. Running ANALYZE on Specific Columns
ANALYZE orders (customer_id, placed_at);
9. Understanding Autovacuum
| Threshold | Formula |
|---|---|
| VACUUM | scale_factor × n_live + threshold < n_dead |
| ANALYZE | scale_factor × n_live + threshold < n_mod_since_analyze |
| Freeze trigger | age(relfrozenxid) > autovacuum_freeze_max_age |
10. Configuring Autovacuum
autovacuum_max_workers = 5
autovacuum_naptime = 30s
autovacuum_vacuum_scale_factor = 0.1
autovacuum_analyze_scale_factor = 0.05
autovacuum_vacuum_cost_limit = 2000
-- Per-table override:
ALTER TABLE big_fact SET (autovacuum_vacuum_scale_factor = 0.02);
11. Monitoring VACUUM Progress
SELECT pid, datname, relid::regclass, phase, heap_blks_scanned, heap_blks_total
FROM pg_stat_progress_vacuum;
12. Checking Last Vacuum Time
SELECT relname, last_vacuum, last_autovacuum, last_analyze, last_autoanalyze
FROM pg_stat_user_tables ORDER BY n_dead_tup DESC;
13. Understanding Dead Tuples
SELECT relname, n_live_tup, n_dead_tup,
round(n_dead_tup::numeric / nullif(n_live_tup,0), 3) AS dead_ratio
FROM pg_stat_user_tables ORDER BY n_dead_tup DESC;
14. Preventing Bloat
| Practice | Detail |
|---|---|
| Tune autovacuum | Lower scale_factor on hot tables |
| Avoid long transactions | They pin dead tuples |
| Use HOT updates | Don't update indexed columns when possible |
| FILLFACTOR < 100 | Leaves room for HOT updates |
| pg_repack / pg_squeeze | Online compaction |