Почему EXPLAIN показывает Seq Scan, хотя индекс есть

Классическая сцена: индекс создан, запрос по индексированной колонке, а план всё равно показывает последовательное чтение. Первая мысль — «индекс сломался». Почти всегда дело в другом.

Таблица маленькая

На тысяче строк планировщик прав: прочитать всё подряд дешевле, чем прыгать по индексу и потом ходить в heap за строками. Проверяется тривиально — залить данных побольше и посмотреть план заново. На учебных таблицах в пару сотен строк индекс не покажет себя никогда.

Статистика устарела

После массовой заливки автовакуум мог ещё не дойти. Планировщик считает селективность по устаревшей картине:

ANALYZE orders;

Условие не sargable

Функция на колонке убивает обычный btree-индекс:

-- индекс не применится
WHERE date_trunc('day', created_at) = '2026-08-28'

-- применится
WHERE created_at >= '2026-08-28' AND created_at < '2026-08-29'

Либо, если первая форма нужна по существу, — индекс по выражению.

Несовпадение типов

Колонка bigint, а в запросе строковый литерал. Приведение типа происходит на стороне колонки, и индекс снова мимо. Смотреть на приведения в тексте плана, они там видны явно.

Отдельно: EXPLAIN без ANALYZE показывает оценку, а не факт. Расхождение оценки и реальности в десятки раз — само по себе диагноз, обычно как раз про статистику.