awesome-everything EN
↑ Обратно к восхождению

Базы данных

Планы выполнения: диагностируй и стабилизируй медленный запрос

Суть Практический проект — спровоцируй раздувание оценки строк на коррелированных колонках в реальном Postgres, диагностируй по EXPLAIN ANALYZE, почини причину и докажи стабильность плана числами до/после.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на senior-высоте — в орбите
◷ 240 min

Читать про каскад ошибок оценки строк — не то же самое, что наблюдать, как Nested Loop отрабатывает полмиллиона раз, потому что планировщик поверил неверному числу. Построй реалистичный датасет, загони запрос в раздувание планировщика и пройди диагностическую дисциплину юнита, пока оценка не сойдётся с реальностью — с доказательством EXPLAIN ANALYZE на каждом шаге.

Цель

Преврати ментальную модель юнита в воспроизводимый цикл: заинструментируй через EXPLAIN ANALYZE и pg_stat_statements, диагностируй каскад оценки строк и generic-plan trap по выводу плана, почини каждое по причине и докажи стабильность плана числами до/после под идентичной нагрузкой.

Проект
0 из 7
Цель

Возьми реальный инстанс Postgres 16, засей коррелированный, перекошенный датасет и загони представительный запрос в раздувание планировщика. Диагностируй причину по EXPLAIN ANALYZE, почини её на уровне statistics / plan-cache (а не форсируя план) и докажи фикс измерениями до/после под одной нагрузкой.

Требования
Критерии приёмки
  • Таблица до/после для целевого запроса: тип scan, алгоритм join, rows-estimated vs actual на ключевом узле, счётчик внутреннего цикла, p99 задержка и mean_exec_time — всё измерено под одной нагрузкой, а не оценено.
  • EXPLAIN ANALYZE после фикса statistics показывает, что estimated отслеживает actual в пределах ~2x на ранее сломанном узле, и план больше не использует раздутый Nested Loop.
  • Доказательство generic-plan trap (бимодальная задержка, высокий stddev_exec_time, вывод GENERIC_PLAN) и его устранения после force_custom_plan, с prepared statement, теперь использующим корректный составной индекс для обоих параметров.
  • Абзац-разбор, называющий причину каждого фикса (предположение о независимости коррелированных колонок; переключение на generic plan) и объясняющий, почему починка оценки или режима plan-cache корректна там, где форсирование плана или перестройка индекса — нет.
Senior-стретч
  • Добавь одностраничный on-call runbook: triage по EXPLAIN ANALYZE (сначала найди самый большой разрыв estimated-vs-actual), типичные причины (устаревшая statistics, коррелированные колонки, non-sargable предикат, generic-plan trap) и чек-лист верификации.
  • Построй пятислойную процедуру деплоя для стабильности планов: снимок pg_stat_statements + EXPLAIN топ-20 до деплоя, ANALYZE и пересъёмка после, и скрипт, диффящий структуру плана и помечающий любую регрессию mean_exec_time свыше 50%.
  • Введи non-sargable предикат (EXTRACT(year FROM created_at) = 2026 или LOWER(email) = 'x'), покажи, что он форсирует Seq Scan + Filter, затем почини range-переписыванием или expression-индексом / expression statistics и докажи, что scan сменился.
  • Форсируй spill work_mem на крупной сортировке или hash join (Sort Method: external merge или Hash Batches > 1), затем подними work_mem посессионно и покажи, как spill исчезает — задокументировав бюджет max_connections x work_mem, который не превысил бы глобально.
Итог

Это цикл, который ты будешь запускать в каждом реальном инциденте медленного запроса в Postgres: сначала инструментируй через EXPLAIN ANALYZE и pg_stat_statements, найди самый большой разрыв rows-estimated vs actual и проследи его к предикату, почини причину — extended statistics для коррелированных колонок, force_custom_plan для перекошенных prepared statements, cost-константы под SSD — и подтверди числами до/после под идентичной нагрузкой. Форсирование плана или перестройка индекса лечат симптом; починка оценки исправляет всё дерево над ней. Сделав это раз на засеянном датасете, ты доводишь production-версию до уровня мышечной памяти.

Продолжить восхождение ↑MVCC: как Postgres раздаёт согласованные снимки
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources2
expand
  1. 01
  2. 02

Trademarks belong to their respective owners. Editorial reference only.