Материалы / Технические статьи / EXPLAIN: с чего начать
Статья

EXPLAIN: с чего начать

Введение в EXPLAIN, EXPLAIN ANALYZE и BUFFERS: чем отличаются планы и как безопасно начинать анализ запросов PostgreSQL.

Лена из поддержки аккуратно постучала в открытую дверь Макса:

— Ты обещал научить меня разбираться с тормозящими запросами. Может, начнём? А то я даже не понимаю, куда смотреть, когда пишут «у вас там план кривой».

Макс отложил кружку с остывшим кофе и убрал с экрана монитора три вкладки с алертами:

— Окей, давай по порядку. Ты видишь в логах, что «запрос выполняется 10 секунд» — это симптом болезни. А EXPLAIN — это рентген, который покажет, где конкретно проблема.

Лена нахмурилась:

— Я так понимаю, что это… инструкция, как Postgres выполняет запрос?

— Почти! — Макс развернул монитор. — Но есть нюансы.

Три вида «рентгена»

Макс открыл новое окно и быстрым движением набрал:

EXPLAIN SELECT * FROM orders WHERE order_type = 10;

1. EXPLAIN — теоретический план

— Смотри, это как маршрут на бумажной карте. Postgres говорит: «Я бы сделал так», но не факт, что в реальности будет так же. Видишь Seq Scan? Это значит, он планирует читать всю таблицу подряд.

2. EXPLAIN ANALYZE — реальное выполнение

Макс добавил ANALYZE:

EXPLAIN ANALYZE SELECT * FROM orders WHERE order_type = 10;

— А это уже как навигатор с пробками. Тут есть реальные цифры: сколько времени заняло, сколько строк обработано. Для простого узла actual rows=1 при rows=1000 означает ошибку оценки в тысячу раз. Если есть повторные выполнения, обязательно учитывай loops: фактические значения показываются в среднем на один цикл.

Лена кивнула:

— То есть если запрос тормозит, сначала смотрим тут?

— Да, но… — Макс ухмыльнулся. — И полезно явно запросить работу с буферами, особенно если ты читаешь план из версии до PostgreSQL 18.

3. EXPLAIN (ANALYZE, BUFFERS) — работа со страницами

EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM orders WHERE order_type = 10;

BUFFERS покажет обращения к shared, local и temp blocks: hit, read, dirtied, written. Но read не доказывает физическое чтение с диска — страница могла находиться в кэше операционной системы. А VERBOSE добавляет структуру выходных столбцов и другие детали.

— И запомни: ANALYZE здесь означает выполнение запроса, а не сбор статистики командой ANALYZE. Для изменяющего SQL побочные эффекты реальны. Даже SELECT может быть тяжёлым, прогреть кэши и повлиять на других пользователей, поэтому продакшен требует отдельной оценки.

Практика

Макс подвинул клавиатуру:

— Давай попробуем. Напиши любой свой запрос, и сделаем к нему EXPLAIN ANALYZE.

Лена ввела что-то вроде:

SELECT count(*) FROM tasks WHERE status = 'new' AND created_at > '2025-01-01';

— Ого! — она указала на цифры. — Seq Scan on tasks, а потом Filter… И он прогнал 500 тыс. строк!

— Вот и кандидат на оптимизацию, — Макс сохранил план в файл. — В следующий раз разберём, как заменить это на Index Scan.

Что запомнить

  • EXPLAIN — только план (без выполнения запроса)

  • EXPLAIN ANALYZE — выполнит запрос и покажет фактические замеры; в PostgreSQL 18 он автоматически включает сведения о буферах

  • EXPLAIN (ANALYZE, BUFFERS) — явно запрашивает сведения о буферах и остаётся понятной переносимой записью для старых версий

На рабочей базе сначала получите план без выполнения и оцените риск фактического запуска. В PostgreSQL 18 ANALYZE автоматически включает BUFFERS; в более ранних поддерживаемых версиях его нужно было указывать отдельно.

  • Сильная разница между rows и actual rows указывает на ошибку оценки; при loops > 1 сравнивайте значения с учётом повторов

Лена потянулась за своим ноутбуком:

— Ладно, теперь я хотя бы понимаю, как смотреть. А что дальше?

Макс ухмыльнулся и показал на строку подключения к тестовой базе:

— Дальше — практика без теории. Просто гоняй любые запросы через EXPLAIN на тестовой базе и смотри, что получается. Не пытайся сразу всё понять — просто привыкай к структуре.

— Даже если я ничего не пойму?

— Особенно если не поймешь! — Макс подвинул ей список команд. — Записывай вопросы:

  • «Что такое Seq Scan, а что такое Index Scan?»

  • «Что значит cost=100500?»

  • «Почему Actual Rows меньше, чем Rows?»

Вопросы присылай — разберём. Главное — перестать бояться этих «иероглифов».

— Окей, попробую. Но если я сломаю тестовую базу…

— Если сломаешь — значит, учишься, — Макс допил кофе. — До завтра!

Практическое задание

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