Почему PostgreSQL не использует созданный индекс и выбирает полный скан таблицы?

По каким причинам PostgreSQL может не использовать индекс планировщик выбирает наименее затратный план (cost-based) индекс малоэффективен при низкой селективности (большом количестве повторяющихся значений) при чтении…

Короткий ответ

Что ответить на собеседовании

По каким причинам PostgreSQL может не использовать индекс планировщик выбирает наименее затратный план (cost-based) индекс малоэффективен при низкой селективности (большом количестве повторяющихся значений) при чтении значительной части данных seq scan работает быстрее статистика устарела, поэтому выполняется неверная оценка в запросе используются функции или выражения, которые индекс не покрывает типы данных либо кодировки не соответствуют индексу при параллельном выполнении предпочтение может отдаваться seq scan на результат влияют настройки конфигурации, включая random_page_cost

Подробный разбор

Ответ с пояснениями

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

  • планировщик выбирает наименее затратный план (cost-based)
  • индекс малоэффективен при низкой селективности (большом количестве повторяющихся значений)
  • при чтении значительной части данных seq scan работает быстрее
  • статистика устарела, поэтому выполняется неверная оценка
  • в запросе используются функции или выражения, которые индекс не покрывает
  • типы данных либо кодировки не соответствуют индексу
  • при параллельном выполнении предпочтение может отдаваться seq scan
  • на результат влияют настройки конфигурации, включая random_page_cost

Итог: PostgreSQL обращается к индексу только тогда, когда считает такой путь более быстрым; в противном случае для оптимальной производительности выбирается full scan.

Подробный ответ

Основной ответ

Даже созданный индекс в PostgreSQL может остаться неиспользованным, если планировщик запросов оценивает полное сканирование таблицы (Seq Scan) как более выгодное по времени и расходу ресурсов. Решение принимается на основании статистики, объема данных и расчетной стоимости различных вариантов выполнения запроса.

Ключевые моменты

  • Статистика и распределение данных: При устаревшей или недостаточно подробной статистике планировщик может ошибиться в оценке числа возвращаемых строк и выбрать full scan. Если запрос извлекает существенную часть таблицы (например, > 5-10%), использование индекса также способно оказаться дороже из-за дополнительных операций random I/O.
  • Условия запроса и фильтрация: Индекс может не применяться при неподходящих условиях, например когда в фильтре используются функции или выражения, которые нельзя эффективно индексировать, либо типы данных не совпадают. Для полнотекстового поиска обычный индекс также не подходит без специализированных индексов GIN или GiST.
  • Настройки конфигурации и размер объектов: Когда таблица небольшая или индекс имеет большой размер, seq scan может завершиться быстрее. На расчет стоимости доступа влияют, в частности, параметры random_page_cost и seq_page_cost в PostgreSQL, поэтому они способны склонить планировщик к полному сканированию.
  • Отсутствие подходящего индекса: Индекс не поможет, если запрос фильтрует по другим полям или не содержит все необходимые колонки. В случае отсутствия покрывающего индекса сканирование таблицы может быть более выгодным вариантом.

Практический контекст

В рабочих проектах следует регулярно выполнять ANALYZE, чтобы обновлять статистику, подбирать подходящий тип индекса — B-tree, GIN или GiST — и анализировать запросы с помощью EXPLAIN ANALYZE. Начиная с PostgreSQL 14 планировщик стал более интеллектуальным, однако контроль параметров конфигурации по-прежнему необходим, чтобы не получать лишние Seq Scan там, где индекс способен работать эффективно.

Практика в реальном времени

Подготовьтесь к следующему собеседованию

Interview Boost учитывает вакансию, резюме и технологии и помогает сформулировать ответ прямо во время интервью.

Начать подготовку