> В чем разница между EXPLAIN и EXPLAIN ANALYZE (Go)

Уровень: middle · Роль: backend · Категория: Технические вопросы

Компании: InDrive, Employcity

Стек: Go

> Пример ответа

Короткий ответ

EXPLAIN показывает план выполнения запроса без его запуска, а EXPLAIN ANALYZE выполняет запрос и добавляет реальную статистику: фактическое время, число строк, затраты на каждом шаге. Разница критична: без ANALYZE вы видите только оценку планировщика, которая может сильно расходиться с реальностью, особенно при устаревшей статистике или сложных JOIN. В PostgreSQL для корректного измерения нужно также использовать ANALYZE, иначе вы рискуете оптимизировать запрос на основе предположений, а не фактов.

Подробное объяснение

EXPLAIN - это команда PostgreSQL (и других СУБД), которая показывает дерево операций, выбранное планировщиком: последовательное сканирование, индексный поиск, hash join, сортировку и т.д. Для каждого узла выводятся оценочные значения: стоимость запуска, общая стоимость, ожидаемое число строк и средний размер строки. Эти оценки основаны на статистике таблиц, собранной командой ANALYZE, и на параметрах конфигурации (например, random_page_cost, cpu_tuple_cost).

EXPLAIN ANALYZE дополнительно выполняет запрос и для каждого узла выводит фактическое время (в миллисекундах), фактическое число строк, число циклов (loops) и время на один цикл. Также показывается общее время выполнения и время планирования. Это позволяет сравнить оценку планировщика с реальностью: если оценки сильно отличаются, значит, статистика устарела или планировщик выбрал неоптимальный план.

Ключевые различия:

  • Выполнение: EXPLAIN не выполняет запрос, EXPLAIN ANALYZE выполняет. Это значит, что ANALYZE может изменить данные (INSERT, UPDATE, DELETE) и имеет побочные эффекты.
  • Точность: EXPLAIN даёт только прогноз, ANALYZE - факт. Прогноз может быть неточным из-за корреляций в данных, неполной статистики или сложных выражений.
  • Время: EXPLAIN мгновенный, ANALYZE занимает столько же, сколько сам запрос, плюс накладные расходы на измерение.
  • Безопасность: EXPLAIN безопасен для production, ANALYZE - нет, если запрос модифицирует данные (нужно оборачивать в транзакцию с ROLLBACK).
  • Дополнительная информация: ANALYZE показывает фактическое число строк на каждом шаге, что помогает найти узкие места, например, когда планировщик ожидает 10 строк, а получает 100 000.

Также есть модификаторы: EXPLAIN (ANALYZE, BUFFERS) добавляет информацию о чтении/записи буферов, EXPLAIN (ANALYZE, FORMAT JSON) - машинно-читаемый вывод. В PostgreSQL 14+ появился EXPLAIN (ANALYZE, TIMING OFF) для уменьшения накладных расходов.

На практике

Для backend-разработчика на Go, работающего с PostgreSQL, EXPLAIN и EXPLAIN ANALYZE - основные инструменты диагностики медленных запросов. Типичный сценарий: приложение тормозит на конкретном SQL, вы берёте его, подставляете реальные параметры и запускаете EXPLAIN ANALYZE. Если видите Seq Scan на большой таблице, где ожидался Index Scan, или Nested Loop с миллионами итераций - это сигнал к добавлению индекса или переписыванию запроса.

Важно помнить: EXPLAIN ANALYZE выполняет запрос, поэтому для SELECT это безопасно, но для модифицирующих запросов нужно использовать транзакцию:

SQL
BEGIN;
EXPLAIN ANALYZE UPDATE users SET status = 'active' WHERE last_login < now() - interval '1 year';
ROLLBACK;

Также стоит учитывать, что в Go-приложениях часто используют пул соединений, и параметры запроса могут отличаться от тех, что вы тестируете в psql. Поэтому всегда подставляйте реальные значения, а не плейсхолдеры.

При сравнении планов обращайте внимание на:

  • фактическое число строк (actual rows) против ожидаемого (rows) - расхождение в разы указывает на проблему со статистикой;
  • время на самом дорогом узле - обычно это join или сортировка;
  • число циклов (loops) - если больше 1, узел выполняется многократно, что может быть узким местом.

Пример кода

SQL
-- Простой EXPLAIN: только план, без выполнения
EXPLAIN SELECT * FROM orders WHERE user_id = 42;
-- Результат (пример):
-- Seq Scan on orders (cost=0.00..35.50 rows=10 width=220)
-- Filter: (user_id = 42)
-- EXPLAIN ANALYZE: выполняет запрос и показывает факты
EXPLAIN ANALYZE SELECT * FROM orders WHERE user_id = 42;
-- Результат (пример):
-- Seq Scan on orders (cost=0.00..35.50 rows=10 width=220) (actual time=0.015..0.018 rows=3 loops=1)
-- Filter: (user_id = 42)
-- Rows Removed by Filter: 997
-- Planning Time: 0.042 ms
-- Execution Time: 0.031 ms
SQL
-- Для модифицирующих запросов - оборачиваем в транзакцию
BEGIN;
EXPLAIN ANALYZE DELETE FROM sessions WHERE expires_at < now();
ROLLBACK;
SQL
-- С расширенной информацией о буферах
EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM orders WHERE user_id = 42;

Как отвечать на собеседовании

Начните с главного: EXPLAIN - это план без выполнения, EXPLAIN ANALYZE - выполнение с реальной статистикой. Затем добавьте, что ANALYZE полезен для поиска расхождений между оценкой и фактом, но опасен для модифицирующих запросов. Упомяните, что в PostgreSQL есть дополнительные опции (BUFFERS, FORMAT JSON). Если спросят про Go - скажите, что обычно диагностика происходит через psql или встроенные инструменты типа pg_stat_statements, а в коде можно логировать медленные запросы и анализировать их отдельно.

Что проверяет интервьюер

Интервьюер хочет убедиться, что вы понимаете: планировщик работает на основе статистики, которая может быть неточной, и что реальное выполнение - единственный способ увидеть правду. Также проверяется знание побочных эффектов ANALYZE и умение читать вывод. Для middle-позиции важно показать, что вы не просто заучили синтаксис, а понимаете, как применять это для оптимизации.

Типичные ошибки

  • Утверждение, что EXPLAIN ANALYZE не выполняет запрос - это грубая ошибка.
  • Использование EXPLAIN ANALYZE для UPDATE/DELETE без транзакции с ROLLBACK - можно случайно изменить данные в production.
  • Игнорирование расхождения между rows и actual rows - главный источник неправильных выводов.
  • Запуск ANALYZE на больших запросах в production без ограничения времени - запрос может выполняться минуты.
  • Сравнение времени выполнения разных запросов без учёта кеша: первый запуск может быть медленнее из-за чтения с диска.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью