Перейти к основному содержимому

EXPLAIN

примечание

Эта страница переведена при помощи нейросети GigaChat.

EXPLAIN - вывод плана выполнения оператора.

Синтаксис

EXPLAIN [ ( option [, ...] ) ] statement
EXPLAIN [ ANALYZE ] [ VERBOSE ] statement

Где option может быть одной из:

ANALYZE [ boolean ]
VERBOSE [ boolean ]
COSTS [ boolean ]
SETTINGS [ boolean ]
GENERIC_PLAN [ boolean ]
BUFFERS [ boolean ]
SERIALIZE [ { NONE | TEXT | BINARY } ]
WAL [ boolean ]
TIMING [ boolean ]
SUMMARY [ boolean ]
MEMORY [ boolean ]
FORMAT { TEXT | XML | JSON | YAML }

Описание

EXPLAIN отображает план выполнения, который генерирует планировщик PostgreSQL для заданного оператора. План выполнения показывает, как будут сканироваться таблицы, упомянутые в операторе — с помощью последовательного чтения, индексного поиска и так далее. Если задействовано несколько таблиц, также указывается, какой алгоритм соединения будет использоваться для объединения строк из разных таблиц.

Наиболее важной частью вывода являются оценки стоимости выполнения — предположение планировщика о том, сколько ресурсов потребуется для выполнения запроса (в условных единицах, обычно отражающих количество обращений к страницам на диске). Отображаются два значения:

  • стоимость запуска — до получения первой строки;
  • общая стоимость — до получения всех строк.

Обычно важна общая стоимость, но в некоторых случаях (например, подзапрос с EXISTS) выбирается план с минимальной стартовой стоимостью, так как выполнение прекращается после первой строки. При использовании LIMIT планировщик делает интерполяцию между стартовой и полной стоимостью, чтобы выбрать наименее затратный план.

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

Важно

Имейте в виду, что оператор фактически выполняется при использовании ANALYZE. Хотя EXPLAIN отбросит любой вывод, который мог бы вернуть SELECT, другие побочные эффекты оператора будут происходить как обычно. Если нужно использовать EXPLAIN ANALYZE для INSERT, UPDATE, DELETE, MERGE, CREATE TABLE AS или EXECUTE оператора без воздействия команды на данные, используйте этот подход:

BEGIN;
EXPLAIN ANALYZE ...;
ROLLBACK;

Параметры

ANALYZE
Выполняет команду и добавляет статистику выполнения. По умолчанию FALSE.
VERBOSE
Выводит дополнительную информацию: список выходных столбцов для каждого узла плана, имена таблиц и функций с указанием схем, имена переменных, имена триггеров и идентификатор запроса (если включен compute_query_id). По умолчанию FALSE.
COSTS
Показывает оценочную стартовую и общую стоимость, количество строк и ширину строк для каждого узла плана. По умолчанию TRUE.
SETTINGS
Показывает параметры конфигурации, отличающиеся от значений по умолчанию и влияющие на планирование. По умолчанию FALSE.
GENERIC_PLAN
Позволяет оператору содержать заполнители параметров, подобные $1, и генерировать общий план, который не зависит от значений этих параметров. См. раздел PREPARE для получения подробностей об общих планах и типах операторов, поддерживающих параметры. Этот параметр нельзя использовать совместно с ANALYZE. Он принимает значение по умолчанию FALSE.
BUFFERS
Включите информацию об использовании буферов. В частности, включите количество совпадающих блоков общего доступа, считанных, испорченных и записанных блоков, количество локальных совпадающих блоков, считанных, испорченных и записанных блоков, количество временных блоков, считываемых и записываемых, а также время, потраченное на чтение и запись блоков данных файлов, локальных блоков и временных файловых блоков (в миллисекундах), если включена опция track_io_timing. Совпадение hit означает, что операция чтения была предотвращена, поскольку блок уже находился в кеше при необходимости. Общие блоки содержат данные из обычных таблиц и индексов. Локальные блоки содержат данные из временных таблиц и индексов. Временные блоки содержат краткосрочные рабочие данные, используемые при сортировке, хешировании, узлах плана Materialize и аналогичных случаях. Число блоков dirtied указывает количество ранее неизмененных блоков, измененных этим запросом, число блоков written указывает количество ранее загрязненных блоков, вытесненных из кеша данным сервером во время обработки запроса. Количество блоков, указанное для верхнего уровня узла, включает те, которые используются всеми его дочерними узлами. В текстовом формате отображаются только ненулевые значения. По умолчанию этот параметр равен FALSE.
SERIALIZE
Включить информацию о стоимости сериализации выходных данных запроса, то есть преобразования их в текстовый или двоичный формат для отправки клиенту. Это может составлять значительную часть времени, необходимого для обычного выполнения запроса, если функции вывода типов данных дороги или необходимо извлечь значения TOAST из внестрочного хранилища. Поведение EXPLAIN по умолчанию, SERIALIZE NONE, не выполняет таких преобразований. Если указано SERIALIZE TEXT или SERIALIZE BINARY, выполняются соответствующие преобразования, и измеряется время, затрачиваемое на них (если не указана опция TIMING OFF). Если также указан параметр BUFFERS, то учитываются любые обращения к буферам, связанные с этими преобразованиями. Однако ни в коем случае EXPLAIN не отправляет полученные данные клиенту, следовательно, таким образом невозможно исследовать затраты на передачу по сети. Сериализация возможна только тогда, когда также включен параметр ANALYZE. Если SERIALIZE написано без аргумента, предполагается TEXT.
WAL
Показывает информацию о создании WAL-записей: количество записей, образов страниц (FPI) и общий объем в байтах. Работает только при ANALYZE = TRUE. По умолчанию FALSE.
TIMING
Показывает фактическое время старта и выполнения каждого узла. На некоторых платформах это может значительно замедлить выполнение, поэтому можно отключить. Общее время выполнения всегда отображается. Работает только при ANALYZE = TRUE. По умолчанию TRUE.
SUMMARY
Показывает сводную информацию после плана (включается по умолчанию с ANALYZE, но отключена без него). Включает, например, суммарное время выполнения. Планирование в EXPLAIN EXECUTE учитывает время извлечения плана из кеша и время перепланирования, если оно произошло.
MEMORY
Включить информацию о потреблении памяти фазой планирования запросов. В частности, укажите точное количество используемой оперативной памяти структурами данных генератора планов, а также общую память с учетом накладных расходов на выделение. Этот параметр по умолчанию равен FALSE.
FORMAT
Указывает формат вывода: TEXT, XML, JSON, YAML. Все форматы содержат одинаковую информацию, но машинные форматы проще парсить. По умолчанию TEXT.
boolean
Указывает, включен параметр или нет: TRUE, ON, 1 — включено; FALSE, OFF, 0 — выключено. Можно опустить значение — считается, что параметр включен.
statement
Любое SELECT, INSERT, UPDATE, DELETE, MERGE, VALUES, EXECUTE, DECLARE, CREATE TABLE AS, или CREATE MATERIALIZED VIEW AS утверждение, план выполнения которого необходимо увидеть.

Выводимая информация

Результат команды представляет собой текстовое описание выбранного плана выполнения, при необходимости дополненное статистикой выполнения.

Примечания

Чтобы планировщик PostgreSQL мог точно оценивать планы, данные в представлении pg_statistic должны быть актуальны. Обычно этим занимается автоочистка (autovacuum). Однако при существенных изменениях в таблице может потребоваться вручную вызвать ANALYZE.

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

Примеры

Чтобы показать план простого запроса для таблицы с одним столбцом integer и 10000 строк:

EXPLAIN SELECT * FROM foo;

QUERY PLAN
---------------------------------------------------------
Seq Scan on foo (cost=0.00..155.00 rows=10000 width=4)
(1 row)

Вот тот же запрос с форматом вывода JSON:

EXPLAIN (FORMAT JSON) SELECT * FROM foo;
QUERY PLAN
--------------------------------
[ +
{ +
"Plan": { +
"Node Type": "Seq Scan",+
"Relation Name": "foo", +
"Alias": "foo", +
"Startup Cost": 0.00, +
"Total Cost": 155.00, +
"Plan Rows": 10000, +
"Plan Width": 4 +
} +
} +
]
(1 row)

Если есть индекс и используется запрос с условием индексации WHERE, EXPLAIN может показать другой план:

EXPLAIN SELECT * FROM foo WHERE i = 4;

QUERY PLAN
--------------------------------------------------------------
Index Scan using fi on foo (cost=0.00..5.98 rows=1 width=4)
Index Cond: (i = 4)
(2 rows)

Вот тот же запрос, но в формате YAML:

EXPLAIN (FORMAT YAML) SELECT * FROM foo WHERE i='4';
QUERY PLAN
-------------------------------
- Plan: +
Node Type: "Index Scan" +
Scan Direction: "Forward"+
Index Name: "fi" +
Relation Name: "foo" +
Alias: "foo" +
Startup Cost: 0.00 +
Total Cost: 5.98 +
Plan Rows: 1 +
Plan Width: 4 +
Index Cond: "(i = 4)"
(1 row)

Формат XML оставлен для читателя в качестве упражнения.

Вот тот же план с подавленными оценками затрат:

EXPLAIN (COSTS FALSE) SELECT * FROM foo WHERE i = 4;

QUERY PLAN
----------------------------
Index Scan using fi on foo
Index Cond: (i = 4)
(2 rows)

Вот пример плана запроса для запроса, использующего агрегатную функцию:

EXPLAIN SELECT sum(i) FROM foo WHERE i < 10;

QUERY PLAN
-------------------------------------------------------------------​--
Aggregate (cost=23.93..23.93 rows=1 width=4)
-> Index Scan using fi on foo (cost=0.00..23.92 rows=6 width=4)
Index Cond: (i < 10)
(3 rows)

Вот пример использования EXPLAIN EXECUTE для отображения плана выполнения подготовленного запроса:

PREPARE query(int, int) AS SELECT sum(bar) FROM test
WHERE id > $1 AND id < $2
GROUP BY foo;

EXPLAIN ANALYZE EXECUTE query(100, 200);

QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------
HashAggregate (cost=10.77..10.87 rows=10 width=12) (actual time=0.043..0.044 rows=10 loops=1)
Group Key: foo
Batches: 1 Memory Usage: 24kB
-> Index Scan using test_pkey on test (cost=0.29..10.27 rows=99 width=8) (actual time=0.009..0.025 rows=99 loops=1)
Index Cond: ((id > 100) AND (id < 200))
Planning Time: 0.244 ms
Execution Time: 0.073 ms
(7 rows)

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

Обратите внимание, что предыдущий пример показал «индивидуальный» план для конкретных значений параметров, указанных в команде EXECUTE. Можно захотеть увидеть общий план для параметризованного запроса, который можно сделать с помощью команды EXPLAIN (FORMAT TEXT):

EXPLAIN (GENERIC_PLAN)
SELECT sum(bar) FROM test
WHERE id > $1 AND id < $2
GROUP BY foo;

QUERY PLAN
-------------------------------------------------------------------------------
HashAggregate (cost=26.79..26.89 rows=10 width=12)
Group Key: foo
-> Index Scan using test_pkey on test (cost=0.29..24.29 rows=500 width=8)
Index Cond: ((id > $1) AND (id < $2))
(4 rows)

В данном случае парсер правильно определил, что параметры $1 и $2 должны иметь такой же тип данных, как и столбец my_column, так что отсутствие информации о типах параметров из команды PREPARE не было проблемой. В других случаях может понадобиться явно указать типы данных для символов параметров, что можно сделать путем их приведения, например:

EXPLAIN (GENERIC_PLAN)
SELECT sum(bar) FROM test
WHERE id > $1::integer AND id < $2::integer
GROUP BY foo;

Совместимость

В стандарте SQL нет определения оператора EXPLAIN.

Следующий синтаксис использовался до версии PostgreSQL 9.0 и все еще поддерживается:

EXPLAIN [ ANALYZE ] [ VERBOSE ] statement

Обратите внимание, что в этом синтаксисе опции должны указываться именно в том порядке, как показано выше.

Смотрите также

ANALYZE