Перейти к содержанию

EXPLAIN

Для анализа производительности запросов в Picodata можно использовать команду EXPLAIN, с помощью которой можно узнать, как будет выглядеть план исполнения запроса. План позволяет наглядно оценить структуру и последовательность действий при выполнении запроса.

В реализацию EXPLAIN заложены следующие принципы:

Синтаксис

EXPLAIN ( facet FMT , ) dml dql

Фасеты (режимы отображения)

RAW BUCKETS LOGICAL FORWARD CONTEXT

Команда EXPLAIN позволяет указывать определенные режимы вывода EXPLAIN, также называемые фасетами. В настоящий момент можно указывать фасеты RAW, LOGICAL, BUCKETS, FORWARD и CONTEXT в любом порядке. Каждый фасет отвечает за конкретную информацию о запросе.

При указании нескольких фасетов одновременно также печатаются их заголовки, позволяющие быстро ориентироваться в выводе. Например:

EXPLAIN (LOGICAL, BUCKETS) SELECT name, id FROM _pico_table;
──────────────────────────────────────────────────────────────────────
 # Logical plan                                                       
──────────────────────────────────────────────────────────────────────

projection (_pico_table.name::string -> name, _pico_table.id::int -> id)
  scan _pico_table

──────────────────────────────────────────────────────────────────────
 # Buckets                                                            
──────────────────────────────────────────────────────────────────────

buckets = any

Если для EXPLAIN не указано ни одного фасета, то фасетами по умолчанию являются LOGICAL и BUCKETS. Таким образом, запросы

EXPLAIN (LOGICAL, BUCKETS) SELECT name, id FROM _pico_table;

и

EXPLAIN SELECT name, id FROM _pico_table;

эквивалентны.

С подробным описанием каждого фасета EXPLAIN можно ознакомиться тут:

  • RAW — низкоуровневый план исполнения запроса.
  • LOGICAL — высокоуровневый план исполнения запроса.
  • BUCKETS — информация о бакетах, участвующих в исполнении запроса.
  • FORWARD — анализ сетевых пересылок, необходимых для исполнения запроса.
  • CONTEXT — прочие переменные среды, влияющие на исполнение запроса.

Достоверность плана

Команда EXPLAIN в Picodata показывает полный план запроса — со всеми операциями, которые реально выполняются, даже если они не следуют напрямую из текста запроса. Например, COUNT(*) в Picodata исполняется путем частичного подсчёта на узлах хранения и финального суммирования результатов. Это следует из вывода фасета LOGICAL:

EXPLAIN (LOGICAL) SELECT COUNT(*) FROM t;
projection (sum(count_1::int)::int -> col_1)
  motion [policy: full, program: ReshardIfNeeded]
    projection (count(*)::int -> count_1)
      scan t

Узел motion отражает перераспределение данных между узлами кластера. Подробнее об этом можно почитать здесь.

Возможность применения к проблемным запросам

Важной особенностью EXPLAIN в Picodata является возможность получить EXPLAIN для запросов, которые приводят к ошибке при исполнении. Так, Picodata всегда старается построить EXPLAIN для синтаксически корректных запросов, даже если они семантически некорректные. Например:

SELECT name, id FROM _pico_table WHERE MAX(id) = 5;
ERROR:  sbroad: Query 1 from EXPLAIN (RAW): Failed to compile SQL statement: misuse of aggregate function MAX()

Тем не менее, Picodata выполнит EXPLAIN от такого запроса:

EXPLAIN (RAW) SELECT name, id FROM _pico_table WHERE MAX(id) = 5;
╭───────────────────╮
 1. Query (ROUTER) 
╰───────────────────╯

SELECT "_pico_table"."name", "_pico_table"."id" FROM "_pico_table" WHERE max (CAST ("_pico_table"."id" as int)) = CAST(5 AS int)

plan:
Failed to compile SQL statement: misuse of aggregate function MAX()

На данный момент у возможности построить EXPLAIN для проблемных запросов есть ограничения:

  • Нельзя получить EXPLAIN для запроса с транзакционным блоком, если он затрагивает более одного бакета.

Возможности форматирования

В Picodata для EXPLAIN также существует опция FMT, которая применяется к фасетам. В случае LOGICAL форматирование применяется к плану. В случае RAW форматирование применяется к локальным SQL-запросам и их планам. Ниже приведены примеры.

Пример с LOGICAL:

EXPLAIN (LOGICAL) SELECT id, item FROM warehouse;
projection (warehouse.id::int -> id, warehouse.item::string -> item)
  scan warehouse

При указании опции FMT вывод форматируется:

EXPLAIN (LOGICAL, FMT) SELECT id, item FROM warehouse;
projection (
  warehouse.id::int -> id,
  warehouse.item::string -> item
)
  scan warehouse

Пример с RAW:

EXPLAIN (RAW) SELECT * FROM warehouse;
╭──────────────────────────╮
 1. Query (WHOLE STORAGE) 
╰──────────────────────────╯

SELECT "warehouse"."id", "warehouse"."item", "warehouse"."type" FROM "warehouse"

plan:
    [0] SCAN TABLE warehouse (~1048576 rows)

При указании опции FMT вывод будет отформатирован:

EXPLAIN (RAW, FMT) SELECT * FROM warehouse;
╭──────────────────────────╮
 1. Query (WHOLE STORAGE) 
╰──────────────────────────╯

SELECT
  "warehouse"."id",
  "warehouse"."item",
  "warehouse"."type"
FROM
  "warehouse"

plan:
    [0] SCAN TABLE warehouse (~1048576 rows)

Опцию FMT полезно использовать при анализе вывода EXPLAIN для сложных запросов. В будущем могут быть добавлены как новые фасеты, так и новые способы форматирования их элементов.