EXPLAIN

Отображает план выполнения запроса.

Синтаксис

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

Где option может быть одним из следующих:

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

Описание

EXPLAIN отображает план запроса, созданный оптимизатором YMatrix или Postgres для указанного оператора. План запроса — это дерево операций для узла. Каждый узел в плане представляет собой отдельную операцию, например сканирование таблицы, соединение, агрегацию или сортировку.

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

Вывод команды EXPLAIN содержит одну строку для каждого узла дерева плана, показывающую основной тип узла и следующие оценки стоимости, сделанные планировщиком при выполнении этого узла:

  • cost — Оптимизатор предполагает, сколько времени потребуется на выполнение оператора (измеряется в условных единицах стоимости, обычно соответствующих чтению страниц диска). Отображаются два значения стоимости: стоимость запуска до возврата первой строки и общая стоимость возврата всех строк. Обратите внимание, что общая стоимость предполагает получение всех строк, но не всегда это происходит (например, при использовании LIMIT).
  • rows — Общее количество строк, выдаваемых данным узлом плана. Обычно это значение меньше фактического количества строк, обработанных или просканированных узлом, так как учитывается оценка отбора по условиям WHERE. В идеале оценка количества строк на верхнем уровне должна приближаться к реальному числу строк, возвращённых, обновлённых или удалённых запросом.
  • width — Общий объём в байтах всех строк, выдаваемых данным узлом плана.

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

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

  • Общее время (в миллисекундах), затраченное на выполнение запроса.
  • Количество рабочих процессов (сегментов), участвующих в операции данного узла плана. Учитываются только сегменты, возвращающие строки.
  • Максимальное количество строк, возвращённых сегментом, который вернул больше всего строк. Если несколько сегментов возвращают одинаковое количество строк, выбирается тот, у которого наибольшее время завершения.
  • Идентификатор сегмента (segment ID), вернувшего наибольшее количество строк для операции.
  • Для соответствующих операций указывается использование work_mem. Если work_mem недостаточно для выполнения операции в памяти, в плане будет показано, какой объём данных был выгружен на диск и сколько проходов данных потребовалось для самого медленного сегмента. Например:
    Work_mem used: 64K bytes avg, 64K bytes max (seg0). Work_mem wanted: 90K bytes avg, 90K bytes max (seg0) to abate workfile I/O affecting 2 workers. [seg0] pass 0: 488 groups made from 488 rows; 263 rows written to workfile [seg0] pass 1: 263 groups made from 263 rows
  • Время в миллисекундах, затраченное на получение первой строки из сегмента, вернувшего наибольшее количество строк, и общее время получения всех строк из этого сегмента. Если время получения первой строки совпадает с общим временем, оно может быть опущено.

Примечание: имейте в виду, что при использовании ANALYZE оператор действительно выполняется. Хотя EXPLAIN ANALYZE игнорирует результаты SELECT, другие побочные эффекты оператора происходят в обычном порядке. Если вы хотите использовать EXPLAIN ANALYZE для DML-оператора, не влияя при этом на данные, используйте следующий подход:

BEGIN;
EXPLAIN ANALYZE ...;
ROLLBACK;

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

Параметры

ANALYZE

  • Выполнить команду и отобразить фактическое время выполнения и другую статистику. Если этот параметр опущен, по умолчанию используется FALSE. Указание ANALYZE true включает его.

VERBOSE

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

COSTS

  • Включить информацию об оценочной стоимости запуска и общей стоимости для каждого узла плана, а также об оценочном количестве строк и среднем размере каждой строки. Если параметр опущен, по умолчанию используется TRUE; укажите COSTS false, чтобы отключить его.

BUFFERS

  • Включить информацию об использовании буферов. В частности, количество обращений к общим блокам (shared blocks hits), их чтений, изменений (dirtied) и записей, количество обращений к локальным блокам (local blocks hits), их чтений, изменений и записей, а также количество чтений и записей временных блоков (temporary blocks). Обращение (hit) означает, что чтение было избежано, потому что блок уже находился в кэше. Общие блоки содержат данные из обычных таблиц и индексов; локальные блоки — из временных таблиц и индексов; временные блоки используются для хранения промежуточных данных при сортировке, хешировании, материализации узлов плана и аналогичных операций. Количество изменённых блоков (dirtied) показывает число ранее неизменённых блоков, которые были изменены запросом; количество записанных блоков (written) — число блоков, выгруженных из кэша во время обработки запроса. Значения для родительского узла включают значения всех его дочерних узлов. В текстовом формате выводятся только ненулевые значения. Этот параметр доступен только если включён также ANALYZE. По умолчанию — FALSE; укажите BUFFERS true, чтобы включить его.

TIMING

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

FORMAT

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

boolean

  • Указывает, включать или отключать выбранную опцию. Для включения можно использовать TRUE, ON или 1, для отключения — FALSE, OFF или 0. Логическое значение может быть опущено, тогда подразумевается TRUE.

statement

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

Примечание

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

SQL-операторы, выполняемые в рамках команды EXPLAIN ANALYZE, исключаются из очереди ресурсов базы данных YMatrix.

Пример

Чтобы проиллюстрировать, как читать план выполнения EXPLAIN, рассмотрим пример очень простого запроса:

EXPLAIN SELECT * FROM names WHERE name = 'Joelle';
                                  QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Gather Motion 3:1  (slice1; segments: 3)  (cost=0.00..431.27 rows=1 width=58)
   ->  Seq Scan on names  (cost=0.00..431.27 rows=1 width=58)
         Filter: (name = 'Joelle'::text)
 Optimizer: Pivotal Optimizer (GPORCA) version 3.23.0
(4 rows)

Если читать план снизу вверх, оптимизатор начинает с последовательного сканирования таблицы names. Обратите внимание, что условие WHERE используется как фильтр. Это означает, что операция сканирования будет проверять условие для каждой строки и возвращать только те строки, которые ему удовлетворяют.

Результат операции сканирования передаётся в операцию gather motion. В базе данных YMatrix gather motion означает отправку строк сегментов на мастер. В данном случае 3 экземпляра сегментов передают данные одному мастер-экземпляру (3:1). Эта операция выполняется на slice1 параллельного плана выполнения запроса. В YMatrix план запроса разделяется на несколько срезов (slices), чтобы различные части плана могли обрабатываться параллельно этими сегментами.

Оценочная стоимость запуска плана составляет 00.00 (отсутствие затрат), а общая стоимость — 431.27. Оптимизатор оценивает, что данный запрос вернёт одну строку.

Тот же самый запрос, но с подавлением оценки стоимости:

EXPLAIN (COSTS FALSE) SELECT * FROM names WHERE name = 'Joelle';
                QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------
 Gather Motion 3:1  (slice1; segments: 3)
   ->  Seq Scan on names
         Filter: (name = 'Joelle'::text)
 Optimizer: Pivotal Optimizer (GPORCA) version 3.23.0
(4 rows)

Тот же запрос с использованием формата JSON:

EXPLAIN (FORMAT JSON) SELECT * FROM names WHERE name = 'Joelle';
                  QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------
 [                                            +
   {                                          +
     "Plan": {                                +
       "Node Type": "Gather Motion",          +
       "Senders": 3,                          +
       "Receivers": 1,                        +
       "Slice": 1,                            +
       "Segments": 3,                         +
       "Gang Type": "primary reader",         +
       "Startup Cost": 0.00,                  +
       "Total Cost": 431.27,                  +
       "Plan Rows": 1,                        +
       "Plan Width": 58,                      +
       "Plans": [                             +
         {                                    +
           "Node Type": "Seq Scan",           +
           "Parent Relationship": "Outer",    +
           "Slice": 1,                        +
           "Segments": 3,                     +
           "Gang Type": "primary reader",     +
           "Relation Name": "names",          +
           "Alias": "names",                  +
           "Startup Cost": 0.00,              +
           "Total Cost": 431.27,              +
           "Plan Rows": 1,                    +
           "Plan Width": 58,                  +
           "Filter": "(name = 'Joelle'::text)"+
         }                                    +
       ]                                      +
     },                                       +
     "Settings": {                            +
       "Optimizer": "Pivotal Optimizer (GPORCA) version 3.23.0"      +
     }                                        +
   }                                          +
 ]
(1 row)

Если существует индекс и используется запрос с условием WHERE, допускающим использование индекса, EXPLAIN может показать другой план. Данный запрос использует формат YAML для генерации плана со сканированием по индексу:

EXPLAIN (FORMAT YAML) SELECT * FROM NAMES WHERE LOCATION='Sydney, Australia';
                          QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------
 - Plan:                                                     +
     Node Type: "Gather Motion"                              +
     Senders: 3                                              +
     Receivers: 1                                            +
     Slice: 1                                                +
     Segments: 3                                             +
     Gang Type: "primary reader"                             +
     Startup Cost: 0.00                                      +
     Total Cost: 10.81                                       +
     Plan Rows: 10000                                        +
     Plan Width: 70                                          +
     Plans:                                                  +
       - Node Type: "Index Scan"                             +
         Parent Relationship: "Outer"                        +
         Slice: 1                                            +
         Segments: 3                                         +
         Gang Type: "primary reader"                         +
         Scan Direction: "Forward"                           +
         Index Name: "names_idx_loc"                         +
         Relation Name: "names"                              +
         Alias: "names"                                      +
         Startup Cost: 0.00                                  +
         Total Cost: 7.77                                    +
         Plan Rows: 10000                                    +
         Plan Width: 70                                      +
         Index Cond: "(location = 'Sydney, Australia'::text)"+
   Settings:                                                 +
     Optimizer: "Pivotal Optimizer (GPORCA) version 3.23.0"
(1 row)

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

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

Смотрите также

ANALYZE