Выбор ответа Senior EXPLAIN и оптимизация обновлено

Подготовленный запрос внезапно стал медленным

Вопрос

Запрос через подготовленный оператор (prepared statement) первые несколько вызовов работает быстро, а потом для редкого значения параметра резко замедляется. Самое вероятное объяснение?

Попробуйте сами

Выберите вариант, и откроется разбор.

Показать ответ и разбор

Коротко

Правильный ответ: После 5 вызовов возможен generic-план, плохой для редких значений параметра. Для подготовленного запроса PostgreSQL первые 5 раз строит custom plan с учётом конкретных значений параметров.

Варианты ответа

  1. Кеш буферов переполнился после пяти вызовов, и данные читаются с диска
  2. Драйвер перестал передавать параметры и выполняет запрос без WHERE
  3. Статистика сбрасывается после каждого пятого выполнения подготовленного запроса
  4. После 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 ошибок.

Термины по теме