Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Що таке generic і custom плани для підготовлених запитів?

Підготовлений запит (prepared statement) розбирається один раз, а виконується багато разів з різними параметрами. PDO і Laravel використовують їх для прив'язки параметрів.

PREPARE find_orders (text) AS SELECT * FROM orders WHERE status = $1;
EXECUTE find_orders('pending');

Для виконання PostgreSQL може використати два види плану:

  • Custom plan - будується для конкретних значень параметрів. Точний, але планування на кожне виконання коштує час.
  • Generic plan - один план для будь-яких значень, без урахування конкретних. Будується раз і перевикористовується.

Як PostgreSQL обирає (plan_cache_mode = auto): перші п'ять виконань - custom-плани. Потім він порівнює їхню середню вартість з вартістю generic-плану і, якщо generic не набагато гірший, переходить на нього.

Де це ламається - перекошені дані:

-- status = 'pending'   - 0.1% рядків → ідеальний Index Scan
-- status = 'completed' - 95% рядків → потрібен Seq Scan

Generic-план не знає, яке значення прийде, і обирає «середній» варіант. Запит, що спершу виконувався за мілісекунди, після п'ятого разу раптом стає повільним для частини значень. Класична загадка «запит повільний лише в застосунку, а в psql - швидкий» (у psql ви виконуєте його з конкретним значенням - custom план).

Що робити:

SET plan_cache_mode = force_custom_plan;   -- для сесії чи ролі

Або точково - для конкретних запитів з перекошеними даними.

Як діагностувати: EXPLAIN EXECUTE find_orders('completed') після шостого виконання показує, чи план уже generic (параметри в ньому виглядають як $1); auto_explain у логах продакшену.

Нюанс PHP: PDO з PDO::ATTR_EMULATE_PREPARES = true підставляє параметри сам і надсилає готовий текст - тоді на сервері підготовлених запитів немає взагалі, і проблеми generic-планів теж. Laravel за замовчуванням для PostgreSQL використовує справжні підготовлені запити.

Докладніше в документації: PREPARE

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання