Low-Medium Impact

Maintain Table Statistics with VACUUM and ANALYZE

Keep statistics fresh for optimal query planning

Why This Matters

Postgres uses table statistics to choose optimal query plans. Stale statistics lead to poor plans - the planner might choose a sequential scan when an index would be faster, or vice versa.

VACUUM and ANALYZE are two critical maintenance operations:

Note: Supabase runs autovacuum automatically. You only need manual VACUUM ANALYZE for large bulk operations or when autovacuum isn't keeping up.

The Problem

Without regular ANALYZE, statistics become stale and query plans degrade:

Incorrect - Stale statistics cause poor plans
-- Table grew from 1,000 to 1,000,000 rows
-- Statistics still show 1,000 rows
-- Planner chooses sequential scan thinking table is small

SELECT * FROM orders 
WHERE customer_id = 123;

-- EXPLAIN shows:
-- Seq Scan on orders (cost=0.00..25.00 rows=100 width=85)
--   Planner thinks: "Small table, seq scan is fine"
--   Reality: 1M rows, should use index!

The Solution

Run VACUUM ANALYZE regularly to keep statistics fresh:

Correct - Fresh statistics enable optimal plans
-- Update statistics for a table
VACUUM ANALYZE orders;

-- Or analyze all tables
VACUUM ANALYZE;

-- After ANALYZE, planner knows table has 1M rows
EXPLAIN SELECT * FROM orders 
WHERE customer_id = 123;

-- Now shows:
-- Index Scan using orders_customer_id_idx (cost=0.42..8.44 rows=100)
--   Planner correctly chooses index!

Autovacuum Configuration

Autovacuum runs automatically, but you may need to tune it for high-write tables:

-- Check autovacuum settings
SHOW autovacuum;
SHOW autovacuum_vacuum_scale_factor;
SHOW autovacuum_analyze_scale_factor;

-- For high-write tables, run ANALYZE more frequently
ALTER TABLE orders 
SET (autovacuum_analyze_scale_factor = 0.01);
-- Analyzes after 1% of rows change (default is 10%)

When to Run Manually

Warning: VACUUM can lock tables. Use VACUUM (without FULL) for regular maintenance - it doesn't block reads/writes. VACUUM FULL requires exclusive locks.

Monitoring Autovacuum

Check if autovacuum is keeping up:

-- Find tables that need vacuuming
SELECT 
  schemaname,
  relname,
  n_dead_tup,
  n_live_tup,
  last_vacuum,
  last_autovacuum,
  last_analyze,
  last_autoanalyze
FROM pg_stat_user_tables
WHERE n_dead_tup > 1000
ORDER BY n_dead_tup DESC;

Monitor Database Health Automatically

Connect your Supabase project to track autovacuum activity and identify tables needing attention.

Start Supabase Audit

Common Mistakes

Learn More