Ответ
Это ключевые команды для анализа и оптимизации производительности запросов в PostgreSQL.
EXPLAIN
Команда EXPLAIN не выполняет сам запрос. Она обращается к планировщику PostgreSQL и показывает предполагаемый (гипотетический) план выполнения запроса. Этот план строится на основе статистики о таблицах, которую собрал ANALYZE (или автовакуум).
Что показывает:
- Последовательность операций (Scan, Join, Sort, Aggregate).
- Оценочную стоимость (
cost) начала выполнения и общую стоимость. - Оценочное количество строк (
rows), которое вернёт каждая операция.
EXPLAIN ANALYZE
Эта команда делает всё то же, что и EXPLAIN, но с одним важным отличием: она реально выполняет запрос. Поэтому её вывод содержит не только предполагаемый план, но и фактические метрики выполнения.
Что добавляется к выводу EXPLAIN:
actual time: Реальное время в миллисекундах, затраченное на выполнение операции (от старта первой строки до получения последней).rows: Фактическое количество строк, возвращённое операцией.loops: Сколько раз выполнялся данный узел плана.Buffers: Информация об использовании буферного кэша (shared-памяти).hitозначает, что блок данных был найден в кэше,read— что он был прочитан с диска.
Пример вывода:
-- План с реальными метриками
EXPLAIN ANALYZE SELECT * FROM users WHERE id = 1;
-- Результат
Index Scan using users_pkey on users (cost=0.29..8.31 rows=1 width=118)
(actual time=0.025..0.026 rows=1 loops=1)
Index Cond: (id = 1)
Buffers: shared hit=4
Ключевое отличие:
EXPLAIN— быстро и безопасно, показывает намерения планировщика. Используется для быстрой оценки плана.EXPLAIN ANALYZE— медленнее (т.к. выполняет запрос) и может быть опасно дляUPDATE/DELETE/INSERTна продуктивной базе. Показывает реальную картину и помогает найти узкие места, где оценка планировщика сильно разошлась с реальностью.
Ответ 18+ 🔞
А, ну это же про ту самую магию, когда твой запрос ползёт как черепаха в сиропе, а ты сидишь и думаешь: "Ну что за хуйня?". Так вот, слушай сюда, сейчас разжую.
Есть у нас две волшебные палочки. Первая — EXPLAIN. Это как посмотреть на карту маршрута, не выходя из дома. Запрос НЕ выполняется, блядь, вообще! Планировщик, этот хитрожопый теоретик, на основе своей статистики (которую собрал ANALYZE) рисует тебе план: "Ага, мол, сначала вот тут посмотрим, потом присоединим вот это, отсортируем, и будет вам счастье, примерно за 5 условных копеек".
Показывает он:
- Что и в каком порядке будет делаться (сканирование, джойны, сортировка).
- Предполагаемую стоимость (
cost) — начало и конец. - Предполагаемое число строк (
rows), которое каждая операция должна выплюнуть.
А теперь вторая палочка, посерьёзнее — EXPLAIN ANALYZE. Это уже не теория, ёпта, это боевые учения с реальными выстрелами. Команда берёт и на самом деле выполняет твой запрос, внатуре! Поэтому, если ты её запустишь на продакшене на каком-нибудь DELETE FROM huge_table, можешь потом идти пить чай. Надолго.
Но зато она показывает не только план, а как всё было на самом деле:
actual time: Реальное время в миллисекундах, за которое операция отстрелялась (от первой строки до последней).rows: Фактическое, блядь, количество строк, а не те фантазии планировщика.loops: Сколько раз эту операцию пришлось повторять.Buffers: Вот это вообще золото! Показывает, как работала память.hit— данные были в кэше (ура!),read— пришлось лезть на медленный диск (пиздец).
Смотри, как это выглядит в жизни:
-- Спрашиваем у системы: "Ну как, справишься?"
EXPLAIN ANALYZE SELECT * FROM users WHERE id = 1;
-- А система отвечает:
Index Scan using users_pkey on users (cost=0.29..8.31 rows=1 width=118)
(actual time=0.025..0.026 rows=1 loops=1) -- О, смотри, оценка и реальность почти сошлись! Красота.
Index Cond: (id = 1)
Buffers: shared hit=4 -- И всё из кэша взяли, вообще огонь!
Так в чём же, блядь, разница, спросишь ты? А разница проще пареной репы:
EXPLAIN— это быстро и безопасно. Как глянуть в гороскоп на день. "Планировщик намекает, что будет вот так". Используешь для быстрой прикидки.EXPLAIN ANALYZE— это уже разбор полётов после реального вылета. Медленнее, может быть опасно на проде, но показывает, где конкретно твой запрос обосрался. Особенно когда в планеrows=1000, аactual rows=1000000. Вот тут-то и начинается самое интересное, ебать мои старые костыли!