Почему PostgreSQL не использует ваш индекс

28 октября 2026 · 7 минут

Индекс создан, запрос простой, а в EXPLAIN всё равно Seq Scan. Планировщик почти всегда прав по-своему: он выбирает план с наименьшей оценочной стоимостью. Задача в том, чтобы понять, откуда взялась оценка.

1. Устаревшая статистика

После массовой загрузки данных autovacuum может ещё не успеть пересчитать статистику. Планировщик думает, что в таблице сто строк, и честно читает её целиком.

ANALYZE orders;
EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM orders WHERE customer_id = 42;

2. Низкая селективность

Если условию соответствует заметная доля строк, последовательное чтение дешевле случайных обращений к страницам. Индекс по полю status с тремя значениями редко помогает — лучше частичный индекс по редкому значению.

CREATE INDEX orders_pending_idx ON orders (created_at) WHERE status = 'pending';

3. Функция или приведение типа в условии

Условие WHERE lower(email) = ... не использует обычный индекс по email. То же происходит, когда параметр приходит из приложения с другим типом и столбец неявно приводится. Решение — индекс по выражению или исправление типа параметра.

4. LIKE с ведущим процентом

B-tree работает только с префиксным поиском. Для LIKE '%abc%' нужен pg_trgm и GIN-индекс.

Итог

Начинайте с EXPLAIN (ANALYZE, BUFFERS) и сравнивайте оценку строк с фактической. Большое расхождение почти всегда указывает на статистику, а не на «сломанный» индекс.