Overview

A sequential scan (Seq Scan in EXPLAIN) reads every heap page and filters each row. It needs no index, and its cost grows linearly with table size. Seeing one in a plan is a prompt to check table size and selectivity, not an automatic reason to add an index.

Rules

  • The planner rightly picks it for small tables and for queries that return a large fraction of rows. It is a problem when it returns a tiny fraction of a large table.
  • Unexpected Seq Scans usually mean stale statistics (run ANALYZE), an index with the wrong column order or operator class (for example LIKE without text_pattern_ops), or a type mismatch or function call on the indexed column in WHERE.
  • To test whether an index would help, SET enable_seqscan = off in one session, EXPLAIN, then RESET. Never set it globally.
  • Find hot spots with pg_stat_user_tables.seq_scan and seq_tup_read.
SELECT relname, seq_scan, seq_tup_read, idx_scan
FROM pg_stat_user_tables ORDER BY seq_tup_read DESC LIMIT 10;