Подготовленный запрос внезапно стал медленным
Вопрос
Запрос через подготовленный оператор (prepared statement) первые несколько вызовов работает быстро, а потом для редкого значения параметра резко замедляется. Самое вероятное объяснение?
Попробуйте сами
Выберите вариант, и откроется разбор.
Показать ответ и разбор
Коротко
Варианты ответа
- Кеш буферов переполнился после пяти вызовов, и данные читаются с диска
- Драйвер перестал передавать параметры и выполняет запрос без
WHERE - Статистика сбрасывается после каждого пятого выполнения подготовленного запроса
- После 5 вызовов возможен generic-план, плохой для редких значений параметраправильный ответ
Разбор
Для подготовленного запроса PostgreSQL первые 5 раз строит custom plan с учётом конкретных значений параметров. Затем он сравнивает стоимость generic-плана со средней стоимостью custom-планов и, если разница невелика, переключается на generic, чтобы не тратить время на планирование. Generic-план не знает значения, и при перекосе данных (99% строк со статусом paid, 1% с new) он может выбрать Seq Scan там, где для редкого значения нужен индекс. Лечится plan_cache_mode = force_custom_plan для этого запроса; настройка (auto, force_custom_plan, force_generic_plan) задаётся на сессию, пользователя или функцию. Статистика и кеш буферов так себя не ведут.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.
Предыдущий вопрос
Почему COUNT(*) на большой таблице медленный
Следующий вопрос
Перекошенная колонка и неверные оценки