EXPLAIN#

EXPLAIN

EXPLAIN

EXPLAIN — показать план выполнения оператора

Синтаксис

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

where option 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.

См. также

ANALYZE