#Что означает ошибка
После ANALYZE PostgreSQL может сменить Index Scan на Seq Scan, даже если индекс существует: планировщик пересчитывает стоимость на основе новых оценок распределения данных. Seq Scan сам по себе не ошибка — для небольших таблиц или невыборочных условий он может быть быстрее. Сначала сравните реальные затраты и оценку числа строк, затем решайте, нужна ли настройка статистики.
#Как различить причины
| Возможная причина | Как узнать | Что делать |
|---|---|---|
| Условия возвращают большую часть таблицыПри высокой доле подходящих строк чтение всей таблицы дешевле случайных обращений через индекс. | EXPLAIN показывает Seq Scan, но время выполнения низкое, Rows Removed by Filter невелико. | Не принуждать индекс, оставить быстрый план. |
| Оценки не совпадают с фактическими строкамиВыборка статистики не отражает редкие значения или зависимость между столбцами. | В EXPLAIN ANALYZE строки rows=... и actual rows=... отличаются в разы. | Исследовать pg_stats, точечно повысить статистику или создать extended statistics при необходимости. |
| Запрос или индекс не совпадаютИндекс по одному столбцу не используется для выражения над ним или другого порядка составных условий. | EXPLAIN не показывает Index Cond, хотя индекс существует. | Сверить условие, типы данных и структуру индекса; не пересоздавать индекс наугад. |
#Пошаговая диагностика и устранение
- Запишите конкретный запрос и показатели до правкиОткройте интерфейс приложения или журнал запросов и найдите один SELECT, который замедлился после обновления статистики. Сохраните точный текст без паролей и личных данных, исходное время выполнения, объём таблицы и доступные планы. Если запрос изменяет данные, не запускайте его с EXPLAIN ANALYZE: последний реально выполняет команду.
- Подключитесь к нужной базе для чтения плановОткройте терминал и psql, либо pgAdmin → база → Tools → Query Tool. Проверьте
SELECT current_database(), version();. Для каждой инструкции ниже подставляйте настоящие названия таблиц и индекса, взятые из базы. Если права запрещают доступ к pg_stats или таблице, не выдавайте себе дополнительные роли. - Снимите план обычным EXPLAINВыполните
EXPLAIN (VERBOSE, COSTS) SELECT ...для конкретного SELECT; он показывает предполагаемый план, не выполняя сам запрос. Найдите Seq Scan, Index Scan или Bitmap Heap Scan, Estimated Rows и стоимость. Если Seq Scan оказался быстрым на маленькой таблице, прекращайте исправление — нет оснований форсировать индекс. - При наличии безопасного окна измерьте реальную выборкуТолько для SELECT, который не вызывает функций с побочными эффектами, согласуйте запуск
EXPLAIN (ANALYZE, BUFFERS) SELECT ...на тестовой копии или при низкой нагрузке. Эта форма действительно выполняет запрос; сравните actual rows, execution time и чтение блоков. Если сервер загружен, используйте прежний план и не запускайте дорогое измерение на рабочем узле. - Проверьте индексы и содержимое статистикиЗапросите
SELECT indexname, indexdef FROM pg_indexes WHERE schemaname='public' AND tablename='orders';с правильной схемой и таблицей. Затем посмотрите столбцы pg_stats для условий выборки, особенно null_frac, n_distinct, most_common_vals. Если название таблицы другое или статистика не видна роли, уточните схему; не пересоздавайте индексы без измерений. - Уточните, когда действительно нужен ANALYZEЕсли после массовых изменений статистика устарела, согласуйте выполнение
ANALYZE public.orders;в периоды допустимой нагрузки — команда читает данные и обновляет статистику, но не удаляет строки. Если ANALYZE уже выполнен и оценки выглядят реалистично, повторять его многократно бессмысленно. В случае крупной секционированной таблицы отдельно проверьте статистику родителя. - Изолированно проверьте влияние способа доступаДля исследовательского сравнения на собственной тестовой копии откройте транзакцию, выполните
SET LOCAL enable_seqscan=off; EXPLAIN SELECT ...; ROLLBACK;. Это лишь диагностический сигнал: принуждённый план может быть медленнее, а отключение последовательного чтения глобально опасно. После ROLLBACK параметр вернётся и в рабочем приложении ничего не изменится. - Исправляйте только подтверждённую причинуЕсли оценки строк ошибаются, разработчик БД может точечно повысить статистику нужных столбцов или создать многоколоночную статистику по тестовому плану; это изменение схемы, требующее копии и сравнения планов. Если индекс не соответствует выражению, проектируйте подходящий индекс на тестовой базе. Если новый Seq Scan быстрее прежнего Index Scan, оставьте план без изменений.
- Команды для отдельных ситуацийВыберите только подходящий вариант. Это не одна последовательность: часть команд диагностирует проблему, а часть меняет настройки или данные.
#Воспроизведение и проверка только в отдельной тестовой базе
EXPLAIN SELECT * FROM pg_class WHERE oid=1259;
EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM pg_class WHERE oid=1259;#Как убедиться в исправлении и что делать дальше
Сравните показатели выполнения на одинаковом наборе данных, прогретом кэше и сопоставимой нагрузке. Исправление нужно считать успешным, если реальное время и число прочитанных блоков уменьшились, а не просто появилось слово Index Scan. При ухудшении откатите экспериментальные настройки, сохраните оба плана и передайте их администратору базы.