Перейти к содержанию
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 из 10