IntermediatePerformance & Indexes

Find missing indexes using pg_stat_user_tables

The query

SQL
SELECT
  relname AS table_name,
  seq_scan AS sequential_scans,
  seq_tup_read AS rows_from_seq_scan,
  idx_scan AS index_scans,
  idx_tup_fetch AS rows_from_idx,
  ROUND(idx_scan::NUMERIC / NULLIF(seq_scan + idx_scan, 0) * 100, 1) AS idx_scan_pct
FROM pg_stat_user_tables
WHERE seq_scan > 100  -- frequently scanned
ORDER BY seq_scan DESC;
Tested against PostgreSQL 16

Note

High seq_scan with low idx_scan_pct = missing index. High seq_scan_pct is OK for small tables.