EXPLAIN

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

Синтаксис

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

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

    ANALYZE [ boolean ]
    VERBOSE [ boolean ]
    COSTS [ boolean ]
    SETTINGS [ boolean ]
    BUFFERS [ boolean ]
    WAL [ boolean ]
    TIMING [ boolean ]
    SUMMARY [ boolean ]
    FORMAT { TEXT | XML | JSON | YAML }

Описание

Команда EXPLAIN отображает план выполнения, который планировщик 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. Попаданием (hit) считается ситуация, когда требуемый блок уже находится в кэше и чтения с диска удается избежать. Блоки в общем буфере содержат данные из обычных таблиц и индексов, в локальном — данные из временных таблиц и индексов, тогда как временные блоки предназначены для краткосрочного использования при выполнении сортировки, хэширования, материализации и тому подобных узлов плана. Количество загрязненных блоков (dirtied) показывает, сколько ранее не модифицированных блоков изменила данная операция; в то время как количество записанных блоков (written) показывает, сколько ранее загрязненных блоков вытеснило из кэша этим серверным модулем во время обработки запроса. Количество блоков, показанных для узла верхнего уровня, включает блоки, используемые всеми его дочерними узлами. В текстовом формате печатаются только ненулевые значения. По умолчанию имеет значение 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.

boolean

Указывает, должен ли выбранный параметр быть включен или выключен. Для включения параметра можно написать: TRUE, ON или 1, а для выключения — FALSE, OFF или 0. Значение boolean также может быть опущено; в этом случае предполагается 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