EXPLAIN
EXPLAIN — показать план выполнения оператора
Синтаксис
EXPLAIN [ (параметр
[, ...] ) ]оператор
EXPLAIN [ ANALYZE ] [ VERBOSE ]оператор
Здесь допускаетсяпараметр
: ANALYZE [boolean
] VERBOSE [boolean
] COSTS [boolean
] BUFFERS [boolean
] TIMING [boolean
] FORMAT { TEXT | XML | JSON | YAML }
Описание
Эта команда выводит план выполнения, генерируемый планировщиком PostgreSQL для заданного оператора. План выполнения показывает, как будут сканироваться таблицы, затрагиваемые оператором — просто последовательно, по индексу и т. д. — а если запрос связывает несколько таблиц, какой алгоритм соединения будет выбран для объединения считанных из них строк.
Наибольший интерес в выводимой информации представляет ожидаемая стоимость выполнения оператора, которая показывает, сколько, по мнению планировщика, будет выполняться этот оператор (это значение измеряется в единицах стоимости, которые не имеют точного определения, но обычно это обращение к странице на диске). Фактически выводятся два числа: стоимость запуска до выдачи первой строки и общая стоимость выдачи всех строк. Для большинства запросов важна общая стоимость, но в таких контекстах, как подзапрос в EXISTS
, планировщик будет минимизировать стоимость запуска, а не общую стоимость (так как исполнение запроса всё равно завершится сразу после получения одной строки). Кроме того, если количество возвращаемых строк ограничивается предложением LIMIT
, планировщик интерполирует стоимость между двумя этими числами, выбирая наиболее выгодный план.
С параметром ANALYZE
оператор будет выполнен на самом деле, а не только запланирован. При этом в вывод добавляются фактические сведения о времени выполнения, включая общее время, затраченное на каждый узел плана (в миллисекундах) и общее число строк, выданных в результате. Это помогает понять, насколько близки к реальности предварительные оценки планировщика.
Важно
Имейте в виду, что с указанием ANALYZE
оператор действительно выполняется. Хотя EXPLAIN
отбрасывает результат, который вернул бы SELECT
, в остальном все действия выполняются как обычно. Если вы хотите выполнить EXPLAIN ANALYZE
с командой INSERT
, UPDATE
, DELETE
, CREATE TABLE AS
или EXECUTE
, не допуская изменения данных этой командой, воспользуйтесь таким приёмом:
BEGIN; EXPLAIN ANALYZE ...; ROLLBACK;
Без скобок для этого оператора можно указать только параметры ANALYZE
и VERBOSE
и только в таком порядке. В PostgreSQL до версии 9.0 поддерживался только синтаксис без скобок, однако в дальнейшем ожидается, что все новые параметры будут восприниматься только в скобках.
Параметры
ANALYZE
Выполнить команду и вывести фактическое время выполнения и другую статистику. По умолчанию этот параметр равен
FALSE
.VERBOSE
Вывести дополнительную информацию о плане запроса. В частности, включить список столбцов результата для каждого узла в дереве плана, дополнить схемой имена таблиц и функций, всегда указывать для переменных в выражениях псевдоним их таблицы, а также выводить имена всех триггеров, для которых выдаётся статистика. По умолчанию этот параметр равен
FALSE
.COSTS
Вывести рассчитанную стоимость запуска и общую стоимость каждого узла плана, а также рассчитанное число строк и ширину каждой строки. Этот параметр по умолчанию равен
TRUE
.BUFFERS
Включить информацию об использовании буфера. В частности, вывести число попаданий, блоков прочитанных, загрязненных и записанных в разделяемом и локальном буфере, а также число прочитанных и записанных временных блоков. Попаданием (hit) считается ситуация, когда требуемый блок уже находится в кеше и чтения с диска удаётся избежать. Блоки в общем буфере содержат данные обычных таблиц и индексов, в локальном — данные временных таблиц и индексов, а временные блоки предназначены для краткосрочного использования при выполнении сортировки, хеширования, материализации и подобных узлов плана. Число загрязнённых блоков (dirtied) показывает, сколько ранее не модифицированных блоков изменила данная операция; тогда как число записанных блоков (written) показывает, сколько ранее загрязнённых блоков данный серверный процесс вынес из кеша при обработке запроса. Значения, указываемые для узла верхнего уровня, включают значения всех его дочерних узлов. В текстовом формате выводятся только ненулевые значения. Этот параметр действует только в режиме
ANALYZE
. По умолчанию его значение равноFALSE
.TIMING
Включить в вывод фактическое время запуска и время, затраченное на каждый узел. Постоянное чтение системных часов может значительно замедлить запрос, так что если достаточно знать фактическое число строк, имеет смысл сделать этот параметр равным
FALSE
. Время выполнения всего оператора замеряется всегда, даже когда этот параметр выключен и на уровне узлов время не подсчитывается. Этот параметр действует только в режимеANALYZE
. По умолчанию его значение равноTRUE
.FORMAT
Установить один из следующих форматов вывода: TEXT, XML, JSON или YAML. Последние три формата содержат ту же информацию, что и текстовый, но больше подходят для программного разбора. По умолчанию выбирается формат
TEXT
.boolean
Включает или отключает заданный параметр. Для включения параметра можно написать
TRUE
,ON
или1
, а для отключения —FALSE
,OFF
или0
. Значениеboolean
можно опустить, в этом случае подразумеваетсяTRUE
.оператор
Любой оператор
SELECT
,INSERT
,UPDATE
,DELETE
,VALUES
,EXECUTE
,DECLARE
,CREATE TABLE AS
иCREATE MATERIALIZED VIEW AS
, план выполнения которого вас интересует.
Выводимая информация
Результатом команды будет текстовое описание плана, выбранного для оператора
, возможно, дополненное статистикой выполнения. Представленная информация описана в Разделе 14.1.
Замечания
Чтобы планировщик запросов PostgreSQL был достаточно информирован для эффективной оптимизации запросов, данные в 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=9.54..9.54 rows=1 width=8) (actual time=0.156..0.161 rows=11 loops=1) Group Key: foo -> Index Scan using test_pkey on test (cost=0.29..9.29 rows=50 width=8) (actual time=0.039..0.091 rows=99 loops=1) Index Cond: ((id > $1) AND (id < $2)) Planning time: 0.197 ms Execution time: 0.225 ms (6 rows)
Разумеется, конкретные числа, показанные здесь, зависят от фактического содержимого задействованных таблиц. Также учтите, что эти числа и даже выбранная стратегия выполнения запроса могут меняться от версии к версии PostgreSQL вследствие усовершенствования планировщика. Кроме того, команда ANALYZE
при обработке статистических данных производит случайные выборки, так что оценки стоимости могут меняться при каждом чистом запуске ANALYZE
, даже когда фактическое распределение данных в таблице не меняется.
Совместимость
Оператор EXPLAIN
отсутствует в стандарте SQL.
См. также
ANALYZEpg_xlogdump
pg_xlogdump — display a human-readable rendering of the write-ahead log of a Postgres Pro database cluster
Synopsis
pg_xlogdump
[option
...] [startseg
[endseg
] ]
Description
pg_xlogdump
displays the write-ahead log (WAL) and is mainly useful for debugging or educational purposes.
This utility can only be run by the user who installed the server, because it requires read-only access to the data directory.
Options
The following command-line options control the location and format of the output:
startseg
Start reading at the specified log segment file. This implicitly determines the path in which files will be searched for, and the timeline to use.
endseg
Stop after reading the specified log segment file.
-b
--bkp-details
Output detailed information about backup blocks.
-e
end
--end=
end
Stop reading at the specified log position, instead of reading to the end of the log stream.
-f
--follow
After reaching the end of valid WAL, keep polling once per second for new WAL to appear.
-n
limit
--limit=
limit
Display the specified number of records, then stop.
-p
path
--path=
path
Specifies a directory to search for log segment files or a directory with a
pg_xlog
subdirectory that contains such files. The default is to search in the current directory, thepg_xlog
subdirectory of the current directory, and thepg_xlog
subdirectory ofPGDATA
.-r
rmgr
--rmgr=
rmgr
Only display records generated by the specified resource manager. If
list
is passed as name, print a list of valid resource manager names, and exit.-s
start
--start=
start
Log position at which to start reading. The default is to start reading the first valid log record found in the earliest file found.
-t
timeline
--timeline=
timeline
Timeline from which to read log records. The default is to use the value in
startseg
, if that is specified; otherwise, the default is 1.-V
--version
Print the pg_xlogdump version and exit.
-x
xid
--xid=
xid
Only display records marked with the given transaction ID.
-z
--stats[=record]
Display summary statistics (number and size of records and full-page images) instead of individual records. Optionally generate statistics per-record instead of per-rmgr.
-?
--help
Show help about pg_xlogdump command line arguments, and exit.
Notes
Can give wrong results when the server is running.
Only the specified timeline is displayed (or the default, if none is specified). Records in other timelines are ignored.
pg_xlogdump cannot read WAL files with suffix .partial
. If those files need to be read, .partial
suffix needs to be removed from the file name.