CodePark/ questions / Query plans & optimisation
START PRACTICINGPRACTICE
Backend question · Databases & SQL › Query plans & optimisation

A column has an index, but EXPLAIN shows a sequential scan. What are the usual reasons a query does not use an index?

First, the planner may be right. If the query matches a large share of the rows, or the table is small, a sequential scan is cheaper. Reading the table in order costs less than many random index lookups.

Otherwise, the query often cannot use the index. Common causes:

  • A function or cast on the column, like lower(email) or created_at::date. This needs an expression index (an index built on that expression).
  • A type mismatch. It can force a cast on the column side.
  • A leading wildcard, like LIKE '%abc'. A B-tree index cannot help here. Even LIKE 'abc%' needs the C collation or a text_pattern_ops index.
  • A composite index used without its leading column. If the query has no condition on the first column of the index, the index is a poor fit.

Stale statistics can also make the planner misjudge selectivity (how many rows a condition matches). Run ANALYZE to fix them. Confirm the plan with EXPLAIN ANALYZE. Use SET enable_seqscan = off only to test what the index plan would cost. Never use it as a fix.

  • If a query matches many rows or the table is small, a sequential scan is cheaper.
  • Functions, casts or type mismatches on the column block the index.
  • A leading wildcard LIKE cannot use a B-tree. A prefix LIKE needs the C collation or text_pattern_ops.
  • A composite index is a poor fit without a condition on its leading column.
  • Stale statistics mislead the planner. Verify with EXPLAIN ANALYZE.