EXPLAIN

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


Синтаксис

EXPLAIN [ ( параметр [, ...] ) ] оператор
EXPLAIN [ ANALYZE ] [ VERBOSE ] оператор

где параметром может быть:

    ANALYZE [ логическое_значение ]
    VERBOSE [ логическое_значение ]
    COSTS [ логическое_значение ]
    SETTINGS [ логическое_значение ]
    BUFFERS [ логическое_значение ]
    WAL [ логическое_значение ]
    TIMING [ логическое_значение ]
    SUMMARY [ логическое_значение ]
    FORMAT { TEXT | XML | JSON | YAML }

Описание

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

Наиболее важной частью выводимой информации является расчетная стоимость выполнения оператора, которая представляет собой предположение планировщика о том, сколько времени потребуется для выполнения этого оператора (это значение измеряется в единицах стоимости, которые не имеют точного определения, но обычно подразумевают обращение к странице на диске). На самом деле выводятся два числа: начальная стоимость до выдачи первой строки и общая стоимость выдачи всех строк. Для большинства запросов важна общая стоимость, но в таких контекстах, как подзапрос в EXISTS, планировщик выбирает вместо нее наименьшую стартовую стоимость (так как исполнитель все равно остановится сразу после получения одной строки). Кроме того, если ограничить число возвращаемых строк предложением LIMIT, то планировщик делает подходящую интерполяцию между этими предельными значениями стоимости, выбирая наиболее выгодный план.

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


Важно

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

BEGIN;
EXPLAIN ANALYZE ...;
ROLLBACK;

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


Параметры

ANALYZE

Выполнить команду и показать фактическое время выполнения и другую статистику. По умолчанию этот параметр имеет значение FALSE.

VERBOSE

Вывести дополнительную информацию о плане. В частности, включить список выходных столбцов для каждого узла в дереве плана, имена таблиц и функций, дополненных схемами, всегда помечать переменные в выражениях псевдонимом их диапазонной таблицы, а также выводить имена всех триггеров, для которых отображается статистика. По умолчанию этот параметр имеет значение FALSE.

COSTS

Включить информацию о рассчитанной стоимости запуска и общей стоимости каждого узла плана, а также предполагаемое количество строк и предполагаемую ширину каждой строки. По умолчанию этот параметр имеет значение TRUE.

SETTINGS

Включить информацию о параметрах конфигурации. В частности, включить параметры, влияющие на планирование запроса, имеющие значение, отличное от встроенного значения по умолчанию. По умолчанию этот параметр имеет значение FALSE.

BUFFERS

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

WAL

Включить информацию о генерировании записей WAL. В частности, вывести количество записей, количество полных образов страниц (full page images, fpi) и количество сгенерированных WAL в байтах. В текстовом формате печатаются только ненулевые значения. Этот параметр можно использовать только при включенном параметре ANALYZE. По умолчанию имеет значение FALSE.

TIMING

Включить фактическое время запуска и время, затраченное в каждом узле на выходе. Затраты на многократное чтение системных часов могут замедлить запрос в некоторых системах, поэтому когда требуется только подсчет фактического количества строк, а не точное время, может быть полезно установить этот параметр в FALSE. Время выполнения всего оператора всегда измеряется, даже если вывод времени на уровне узла выключен с помощью этого параметра. Этот параметр можно использовать только при включенном параметре ANALYZE. По умолчанию имеет значение TRUE.

SUMMARY

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

FORMAT

Установить формат вывода, который может быть TEXT, XML, JSON или YAML. Нетекстовые форматы содержат ту же информацию, что и TEXT, но больше подходят для программного анализа. По умолчанию этот параметр имеет значение TEXT.

логическое_значение

Определяет, должен ли выбранный параметр быть включен или выключен. Для включения параметра можно написать: TRUE, ON или 1, а для выключения — FALSE, OFF или 0. Кроме того, логическое_значение можно опустить; в этом случае предполагается TRUE.

оператор

Любой оператор SELECT, INSERT, UPDATE, DELETE, VALUES, EXECUTE, DECLARE, CREATE TABLE AS или CREATE MATERIALIZED VIEW AS, план выполнения которого вы хотите видеть.


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

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


Примечания

Чтобы планировщик запросов QHB мог принимать обоснованные решения при оптимизации запросов, данные в pg_statistic должны быть актуальными для всех таблиц, используемых в запросе. Обычно это автоматически обеспечивает Процесс «Автовакуум». Но если в содержимом таблицы недавно произошли существенные изменения, может потребоваться вручную выполнить ANALYZE, не дожидаясь, пока до них доберется автоочистка.

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


Примеры

Выведение плана простого запроса для таблицы, содержащей единственный столбец integer и 10 000 строк:

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)

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


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

В стандарте SQL команда EXPLAIN не определена.


См. также

ANALYZE