EXPLAIN#
EXPLAIN
EXPLAIN — показать план выполнения оператора
Синтаксис
EXPLAIN [ (option
[, ...] ) ]statement
EXPLAIN [ ANALYZE ] [ VERBOSE ]statement
whereoption
can be one of: ANALYZE [boolean
] VERBOSE [boolean
] COSTS [boolean
] SETTINGS [boolean
] GENERIC_PLAN [boolean
] BUFFERS [boolean
] WAL [boolean
] TIMING [boolean
] SUMMARY [boolean
] FORMAT { TEXT | XML | JSON | YAML }
Описание
Эта команда отображает план выполнения, который генерирует планировщик Tantor BE для предоставленного оператора. План выполнения показывает, как таблицы, на которые ссылается оператор, будут сканироваться - путем простого последовательного сканирования, индексного сканирования и т. д. - и если идет ссылка на несколько таблиц, какие алгоритмы соединения будут использоваться для соединения необходимых строк из каждой входной таблицы.
Самая важная часть отображения - это предполагаемая стоимость выполнения оператора, которая является предположением планировщика о том, сколько времени потребуется для выполнения оператора (измеряется в единицах стоимости, которые произвольны, но обычно означают загрузку страниц диска). Фактически, показываются два числа: стоимость запуска до того, как может быть возвращена первая строка, и общая стоимость для возврата всех строк. Для большинства запросов важна общая стоимость, но в контекстах, таких как подзапрос в EXISTS
, планировщик выберет наименьшую стоимость запуска вместо наименьшей общей стоимости (поскольку исполнитель все равно остановится после получения одной строки). Кроме того, если вы ограничиваете количество возвращаемых строк с помощью предложения LIMIT
,планировщик делает соответствующую интерполяцию между конечными стоимостями, чтобы оценить, какой план на самом деле является самым дешевым.
Опция ANALYZE
вызывает фактическое выполнение оператора, а не только его планирование. Затем к отображению добавляются фактические статистические данные о времени выполнения, включая общее затраченное время в каждом узле плана (в миллисекундах) и общее количество строк, которые он фактически вернул. Это полезно для определения, насколько оценки планировщика близки к реальности.
Важно
Имейте в виду, что оператор фактически выполняется, когда
используется опция ANALYZE
. Хотя
EXPLAIN
отбросит любой вывод, который бы
SELECT
вернул, другие побочные эффекты от
оператора произойдут как обычно. Если нужно использовать
EXPLAIN ANALYZE
на
INSERT
, UPDATE
,
DELETE
, MERGE
,
CREATE TABLE AS
,
или EXECUTE
операторе
без воздействия на ваши данные, используйте этот подход:
BEGIN; EXPLAIN ANALYZE ...; ROLLBACK;
Только опции ANALYZE
и VERBOSE
можно указать, и только в таком порядке, без обрамления списка опций в скобки. До версии PostgreSQL 9.0 поддерживался только синтаксис без скобок. Ожидается, что все новые опции будут поддерживаться только в синтаксисе со скобками.
Параметры
ANALYZE
Выполните команду и покажите фактическое время выполнения и другую статистику. Этот параметр по умолчанию установлен в
FALSE
.VERBOSE
Отображать дополнительную информацию о плане. В частности, включать список выходных столбцов для каждого узла в дереве плана, квалифицировать имена таблиц и функций схемой, всегда помечать переменные в выражениях их псевдонимами в таблице диапазонов и всегда выводить имя каждого триггера, для которого отображаются статистические данные. Идентификатор запроса также будет отображаться, если он был вычислен, см. compute_query_id для получения дополнительной информации. Этот параметр по умолчанию установлен в
FALSE
.COSTS
Включите информацию о предполагаемой стоимости запуска и общей стоимости каждого узла плана, а также о предполагаемом количестве строк и предполагаемой ширине каждой строки. Этот параметр по умолчанию установлен в
TRUE
.SETTINGS
Включите информацию о параметрах конфигурации. В частности, укажите параметры, влияющие на планирование запросов со значением, отличным от встроенного значения по умолчанию. Этот параметр по умолчанию установлен в
FALSE
.GENERIC_PLAN
Разрешить оператору содержать заполнители параметров, такие как
$1
, и создать общий план, который не зависит от значений этих параметров. См.PREPARE
для получения подробной информации об общих планах и типах операторов, которые поддерживают параметры. Этот параметр не может использоваться вместе сANALYZE
. По умолчанию установлено значениеFALSE
.BUFFERS
Включите информацию об использовании буфера. В частности, включите количество общих блоков, которые были найдены, прочитаны, изменены и записаны, количество локальных блоков, которые были найдены, прочитаны, изменены и записаны, количество временных блоков, которые были прочитаны и записаны, и время, затраченное на чтение и запись блоков файлов данных, локальных блоков и временных файловых блоков (в миллисекундах), если track_io_timing включен. Найден означает, что чтение было избегнуто, потому что блок уже был найден в кэше, когда это было необходимо. Общие блоки содержат данные из обычных таблиц и индексов; локальные блоки содержат данные из временных таблиц и индексов; в то время как временные блоки содержат краткосрочные рабочие данные, используемые в сортировках, хэшах, узлах плана Materialize и аналогичных случаях. Количество блоков, измененных, указывает количество ранее не измененных блоков, которые были изменены этим запросом; в то время как количество блоков, записанных, указывает количество ранее измененных блоков, выгруженных из кэша этим бэкендом во время обработки запроса. Количество блоков, показанных для узла верхнего уровня, включает те, которые использовались всеми его дочерними узлами. В текстовом формате печатаются только ненулевые значения. Этот параметр по умолчанию имеет значение
FALSE
.WAL
Включите информацию о генерации записей WAL. В частности, укажите количество записей, количество полных изображений страниц (fpi) и объем сгенерированного WAL в байтах. В текстовом формате печатаются только ненулевые значения. Этот параметр может использоваться только при включенном
ANALYZE
. По умолчанию он установлен вFALSE
.TIMING
Включите фактическое время запуска и время, затраченное на каждый узел, в выводе. издержки на повторное чтение системных часов могут замедлить запрос значительно на некоторых системах, поэтому может быть полезно установить этот параметр в
FALSE
, когда требуются только фактические счетчики строк, а не точные времена. Время выполнения всего оператора всегда измеряется, даже когда отключено время на уровне узла с помощью этой опции. Этот параметр может использоваться только при включенномANALYZE
. По умолчанию он установлен вTRUE
.SUMMARY
Включите сводную информацию (например, информацию о суммарном времени выполнения) после плана запроса. Сводная информация включается по умолчанию при использовании
ANALYZE
, но по умолчанию не включается, но может быть включена с помощью этой опции. Время планирования вEXPLAIN EXECUTE
включает время, необходимое для получения плана из кеша и время, необходимое для повторного планирования, если это необходимо.FORMAT
Укажите формат вывода, который может быть TEXT, XML, JSON или YAML. Не текстовый вывод содержит ту же информацию, что и формат текстового вывода, но его легче обрабатывать программам. Этот параметр по умолчанию установлен в
TEXT
.boolean
Определяет, должна ли быть включена или выключена выбранная опция. Вы можете написать
TRUE
,ON
или1
, чтобы включить опцию, иFALSE
,OFF
или0
, чтобы отключить ее. Значениеboolean
также можно опустить, в этом случае предполагаетсяTRUE
.statement
Любой оператор
SELECT
,INSERT
,UPDATE
,DELETE
,MERGE
,VALUES
,EXECUTE
,DECLARE
,CREATE TABLE AS
илиCREATE MATERIALIZED VIEW AS
, план выполнения которого нужно увидеть.
Выводы
Результат команды - это текстовое описание выбранного плана для statement
, при необходимости аннотированное статистикой выполнения. Раздел 14.1 описывает предоставленную информацию.
Примечания
Для того чтобы позволить планировщику запросов Tantor BE принимать обоснованные решения при оптимизации запросов, данные pg_statistic
должны быть актуальными для всех таблиц, используемых в запросе. Обычно этим занимается демон автоочистки автоматически. Но если таблица недавно претерпела значительные изменения в своем содержимом, вам может потребоваться выполнить ручной ANALYZE
вместо ожидания, пока автоочистка синхронизируется с изменениями.
Для измерения временных затрат на выполнение каждого узла в плане выполнения, текущая реализация EXPLAIN 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)
Конечно, конкретные числа, показанные здесь, зависят от фактического содержимого задействованных таблиц. Также следует отметить, что числа и даже выбранная стратегия запроса могут отличаться в различных версиях Tantor BE из-за улучшений планировщика. Кроме того, команда ANALYZE
использует случайное выборочное исследование для оценки статистики данных; поэтому возможно изменение оценок стоимости после свежего запуска ANALYZE
, даже если фактическое распределение данных в таблице не изменилось.
Обратите внимание, что в предыдущем примере был показан “пользовательский” план
для конкретных значений параметров, указанных в EXECUTE
.
Мы также можем захотеть увидеть общий план для параметризованного
запроса, что можно сделать с помощью GENERIC_PLAN
:
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
должны иметь тот же тип данных,
что и id
, поэтому отсутствие информации о типе параметра
от PREPARE
не было проблемой. В других случаях
может потребоваться явное указание типов для символов параметров, что можно сделать путем приведения типов, например:
EXPLAIN (GENERIC_PLAN) SELECT sum(bar) FROM test WHERE id > $1::integer AND id < $2::integer GROUP BY foo;
Совместимость
В стандарте SQL не определен оператор EXPLAIN
.