Learning Platform
Глоссарий Troubleshooting
Урок 13.01 · 30 мин
Продвинутый
EXPLAINEXPLAIN PLANEXPLAIN PIPELINEEXPLAIN ESTIMATEEXPLAIN SYNTAXquery optimization

EXPLAIN: четыре варианта анализа запросов

Когда запрос работает медленно, первый вопрос — “почему?”. EXPLAIN — это диагностический инструмент, который отвечает на этот вопрос без фактического выполнения запроса (кроме EXPLAIN PLAN с некоторыми настройками). В ClickHouse четыре основных варианта EXPLAIN, каждый раскрывает разный аспект выполнения запроса. В Module 06 урок 02 мы детально разобрали EXPLAIN PIPELINE для понимания процессорного DAG — здесь фокус на все четыре варианта с точки зрения практического performance tuning.


Четыре варианта EXPLAIN

Четыре варианта EXPLAIN
EXPLAIN PLANEXPLAIN PLAN (alias EXPLAIN): логический план выполнения. Ключевая опция indexes=1 показывает, какие PrimaryKey и Skip индексы использовались для pruning гранул. Используйте для диагностики: почему запрос читает слишком много гранул?
EXPLAIN PIPELINEEXPLAIN PIPELINE: физический граф процессоров (DAG). Показывает параллелизм: AggregatingTransform x N, Resize N->M. Ключевая опция: graph=1 для DOT-формата. Используйте для поиска узких мест в параллельном выполнении.
EXPLAIN ESTIMATEEXPLAIN ESTIMATE: оценка rows, marks и parts без выполнения запроса. Читает только метаданные (system.parts) — мгновенная операция. Используйте для быстрой проверки: сколько гранул затронет запрос до его запуска?
EXPLAIN SYNTAXEXPLAIN SYNTAX: нормализация SQL и разрешение алиасов. Показывает запрос после автоматических оптимизаций: удаление 1=1, PREWHERE promotion, alias resolution. Используйте для отладки: что видит оптимизатор после rewrites?
ВариантЧто показываетКлючевые опцииКогда использовать
EXPLAIN PLANЛогический план: Expression, Filter, ReadFromMergeTreeindexes=1, header=1, description=1Диагностика индексов, порядок JOIN
EXPLAIN PIPELINEФизический DAG процессоров с x N потокамиgraph=1 (DOT), compact=0Анализ параллелизма, поиск bottleneck
EXPLAIN ESTIMATEОценка rows/marks/parts без выполненияБыстрая проверка объёма до запуска
EXPLAIN SYNTAXНормализованный SQL после оптимизацийoneline=1Отладка: что видит оптимизатор

EXPLAIN PLAN: логический план с индексами

EXPLAIN PLAN (сокращённо EXPLAIN) показывает логическую структуру запроса. Наиболее полезная опция — indexes=1: она раскрывает, какие индексы использовались для pruning.

-- Логический план с анализом индексов
EXPLAIN PLAN indexes = 1
SELECT max(price)
FROM uk_price_paid
WHERE town = 'LONDON';

Типичный вывод:

Expression (Projection)
  Expression (Before ORDER BY)
    Aggregating
      Expression (Before GROUP BY)
        Filter
          ReadFromMergeTree (uk.uk_price_paid)
          Indexes:
            PrimaryKey
              Keys: town
              Condition: (town in ['LONDON', 'LONDON'])
              Parts: 2/12
              Granules: 41/480

Что читать в выводе:

  • Parts: 2/12 — primary key отсёк 10 из 12 parts
  • Granules: 41/480 — из 480 гранул будут читаться только 41
  • Если видите Parts: 12/12 — primary key не помогает, возможно нужен skip-индекс или переосмысление ORDER BY

Дополнительные опции:

-- Показать заголовки столбцов
EXPLAIN PLAN header = 1
SELECT count(), sum(price) FROM uk_price_paid;

-- Детальные описания узлов
EXPLAIN PLAN description = 1
SELECT * FROM uk_price_paid WHERE town = 'LONDON' LIMIT 10;

EXPLAIN PIPELINE: физический граф процессоров

EXPLAIN PIPELINE показывает, как запрос будет выполнен физически: цепочку процессоров, параллелизм и переходы между потоками. Этот вариант детально рассматривался в Module 06 урок 02 — здесь сосредоточимся на применении для performance tuning.

-- Физический граф параллельного выполнения
EXPLAIN PIPELINE
SELECT max(price) FROM uk_price_paid;

Пример вывода:

(Expression)
ExpressionTransform
  (Aggregating)
  Resize 4 → 1
    AggregatingTransform × 4
      (Expression)
      ExpressionTransform × 4
        (ReadFromMergeTree)
        MergeTreeSelect(pool: ReadPoolInOrder) × 4
WARNING

EXPLAIN PIPELINE может показать меньше потоков, чем задано в max_threads. Это адаптивный параллелизм: при малом объёме данных ClickHouse выделяет только столько потоков, сколько нужно для покрытия доступных гранул. Если max_threads=16, но таблица содержит 4 гранулы — вы увидите x 4, а не x 16. Всегда проверяйте на репрезентативном объёме данных.


EXPLAIN ESTIMATE: оценка без выполнения

EXPLAIN ESTIMATE — самый быстрый способ понять масштаб запроса. Он читает только метаданные parts, не обращаясь к данным:

-- Оценка: сколько гранул будет прочитано?
EXPLAIN ESTIMATE
SELECT max(price)
FROM uk_price_paid
WHERE town = 'LONDON';

Вывод:

database  table          parts  rows      marks
uk        uk_price_paid  2      1048576   41

Интерпретация:

  • parts: 2 — partition pruning сработал, из 12 parts читается 2
  • marks: 41 — будет прочитано 41 гранула (41 * 8192 строк = ~336K строк)
  • rows: 1048576 — оценочное количество строк (по метаданным, не точное)

Используйте EXPLAIN ESTIMATE перед запуском тяжёлого запроса на продакшн-данных, чтобы убедиться, что фильтры работают корректно.


EXPLAIN SYNTAX: нормализация запроса

EXPLAIN SYNTAX показывает запрос после всех автоматических оптимизаций — alias resolution, удаление тавтологий, PREWHERE promotion. Это то, что реально видит оптимизатор:

-- Как оптимизатор видит запрос?
EXPLAIN SYNTAX
SELECT 1 + 1 AS x, x * 2;

Вывод:

SELECT
    (1 + 1) AS x,
    (1 + 1) * 2

Алиас x был заменён исходным выражением — оптимизатор всегда работает с развёрнутыми выражениями.

Практический пример с PREWHERE:

-- Запрос с WHERE
EXPLAIN SYNTAX
SELECT price FROM uk_price_paid WHERE town = 'LONDON' AND price > 500000;

Если optimize_move_to_prewhere=1 (по умолчанию включено), вывод покажет автоматическое перемещение части условий в PREWHERE для снижения I/O.


Новый анализатор (New Analyzer, ClickHouse 24.3+)

Начиная с ClickHouse 24.3, новый анализатор включён по умолчанию. Он существенно меняет форму вывода EXPLAIN PLAN: AST-rewrites и оптимизации происходят до построения логического плана, поэтому вывод может выглядеть иначе по сравнению со старым анализатором.

Для отладки трансформаций нового анализатора используется отдельный вариант:

-- Дерево запроса после passes нового анализатора
EXPLAIN QUERY TREE run_passes = 1
SELECT count() FROM uk_price_paid WHERE town = 'LONDON';

Это полезно при миграции сложных запросов или отладке неожиданного поведения оптимизатора после обновления на 24.3+.


Ключевые выводы

  1. EXPLAIN PLAN indexes=1 — главный инструмент диагностики индексов. Если Parts: N/N — primary key не помогает.
  2. EXPLAIN PIPELINE показывает физический параллелизм. Адаптивный параллелизм может показать меньше потоков, чем max_threads — это нормально при малом объёме данных.
  3. EXPLAIN ESTIMATE — мгновенная оценка масштаба запроса по метаданным. Используйте до запуска тяжёлых запросов.
  4. EXPLAIN SYNTAX раскрывает, что видит оптимизатор: развёрнутые алиасы, PREWHERE promotion, удалённые тавтологии.
  5. Новый анализатор (24.3+) меняет форму вывода EXPLAIN PLAN — AST-rewrites происходят до построения плана. Для отладки анализатора используйте EXPLAIN QUERY TREE.
EXPLAIN в PostgreSQL: FORMAT, BUFFERS, ANALYZE и интерпретация плана Trino EXPLAIN ANALYZE: Fragment plan и distributed execution stats

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 3. Вам нужно узнать, сколько гранул прочитает запрос, не выполняя его фактически. Какой вариант EXPLAIN использовать?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 10