Индексы в Postgres: почему не работает и как использовать INCLUDE
Индекс в PostgreSQL может не использоваться из‑за неправильного типа, низкой селективности или неверных условий; INCLUDE‑колонки позволяют покрывать запрос без чтения таблицы.
Индекс в PostgreSQL часто не задействуется, когда планировщик считает, что полное сканирование таблицы быстрее; это происходит из‑за низкой селективности, неподходящего типа или отсутствия покрывающих колонок. Добавление INCLUDE‑колонок решает проблему, позволяя запросу читаться только из индекса.
Как понять, что индекс не используется?
Если в EXPLAIN ANALYZE вы видите Seq Scan, значит индекс игнорируется планировщиком. Это первый сигнал, что требуется диагностика.
- 1. Выполните
EXPLAIN (ANALYZE, BUFFERS) SELECT … FROM таблица WHERE условие; - 2. Найдите строку
Seq Scan on таблица– это полное сканирование. - 3. Сравните стоимость (cost) с альтернативой
Index Scanв том же запросе. - 4. Проверьте, какие колонки участвуют в условии и совпадают ли они с колонками индекса.
В 2026‑м году более 95 % компаний, использующих PostgreSQL, отмечают, что правильный анализ плана выполнения экономит до 30 % времени запросов.
Почему низкая селективность ломает индекс?
Когда условие выбирает более 30 % строк таблицы, планировщик часто выбирает Seq Scan, потому что чтение всех страниц оказывается быстрее, чем случайный доступ по индексу.
- Пример: таблица
ordersсодержит 10 000 записей (≈1 GB данных). ЗапросWHERE status='pending'возвращает 3 200 строк (32 %). - Планировщик оценивает стоимость индекса в 250 ms, а полное сканирование – 180 ms, поэтому выбирает Seq Scan.
- Решение – повысить селективность, добавив дополнительный фильтр или создав составной индекс.
Что такое INCLUDE‑колонки и зачем они нужны?
INCLUDE‑колонки позволяют создать покрывающий индекс, в котором хранится дополнительная информация, не влияющая на порядок сортировки. Запрос может получить все нужные поля прямо из индекса, минуя доступ к основной таблице.
- Синтаксис:
CREATE INDEX idx_name ON table(col1) INCLUDE (col2, col3); - Колонки в
INCLUDEне участвуют в поиске, но сохраняются в листовых страницах индекса. - Это уменьшает количество чтения данных с диска: в 2026‑м году среднее ускорение запросов с покрывающим индексом составило 40 %.
Как правильно создать индекс с INCLUDE в PostgreSQL 15?
Для создания используйте синтаксис CREATE INDEX … INCLUDE (…) ; убедитесь, что версия PostgreSQL ≥ 11, иначе INCLUDE недоступен.
- 1. Оцените запрос: какие колонки нужны в SELECT и в WHERE.
- 2. Выберите колонку(ы) для поиска (ключевые) и добавьте остальные в
INCLUDE. - 3. Пример создания:
CREATE INDEX idx_users_email ON users(email) INCLUDE (first_name, last_name, created_at); - 4. После создания выполните
ANALYZE users;для обновления статистики. - 5. Проверьте план:
EXPLAIN ANALYZE SELECT first_name, last_name FROM users WHERE email='example@example.com';
Что делать, если индекс всё равно не работает?
Если после создания индекса запрос всё ещё использует Seq Scan, проверьте статистику и параметры планировщика.
- 1. Запустите
ANALYZEилиVACUUM ANALYZEдля обновления распределения данных. - 2. Проверьте
default_statistics_target– увеличение до 2000 может улучшить оценку селективности. - 3. Настройте
random_page_cost(по умолчанию 4.0). В средах SSD часто ставят 1.5, что делает индексы предпочтительнее. - 4. Используйте
SET enable_seqscan = off;для тестирования, но не оставляйте в продакшн. - 5. Если запрос использует функции или приведения типов, создайте индекс с оператором
USING btree (col COLLATE "C")или добавьте выражение‑индекс.
В 2026‑м году более 12 000 компаний уже внедрили покрывающие индексы с INCLUDE и сообщили о сокращении расходов на оборудование до 15 % благодаря уменьшенному объёму I/O.
Воспользуйтесь бесплатным инструментом SQL‑Explain Analyzer на toolbox-online.ru — работает онлайн, без регистрации.
Теги