Понимание выполнения запросов с помощью анализатора
ClickHouse обрабатывает запросы исключительно быстро, но выполнение запроса — это не простая задача. Давайте попробуем понять, как выполняется запрос SELECT
. Для иллюстрации добавим некоторые данные в таблицу в ClickHouse:
Теперь, когда у нас есть некоторые данные в ClickHouse, мы хотим запустить несколько запросов и понять их выполнение. Выполнение запроса разбито на множество шагов. Каждый шаг выполнения запроса можно проанализировать и диагностировать с помощью соответствующего запроса EXPLAIN
. Эти шаги подытожены в таблице ниже:

Давайте посмотрим на каждую сущность в действии во время выполнения запроса. Мы возьмем несколько запросов и затем рассмотрим их с помощью оператора EXPLAIN
.
Парсер
Цель парсера — преобразовать текст запроса в AST (абстрактное синтаксическое дерево). Этот шаг можно визуализировать, используя EXPLAIN AST
:
Вывод — это абстрактное синтаксическое дерево, которое можно визуализировать следующим образом:

Каждый узел имеет соответствующие дочерние элементы, и все дерево представляет собой общую структуру вашего запроса. Это логическая структура, помогающая в обработке запроса. С точки зрения конечного пользователя (если не интересует выполнение запроса) она не очень полезна; этот инструмент в основном используется разработчиками.
Анализатор
В настоящее время ClickHouse имеет две архитектуры для анализатора. Вы можете использовать старую архитектуру, установив: enable_analyzer=0
. Новая архитектура включена по умолчанию. Мы собираемся описать только новую архитектуру здесь, поскольку старая будет устаревать, как только новый анализатор станет общедоступным.
Новая архитектура должна обеспечить нам лучшую основу для улучшения производительности ClickHouse. Однако, учитывая, что она является важным компонентом шагов обработки запросов, она также может отрицательно повлиять на некоторые запросы, и существуют известные несовместимости. Вы можете вернуться к старому анализатору, изменив настройку enable_analyzer
на уровне запроса или пользователя.
Анализатор является важным шагом выполнения запроса. Он принимает AST и преобразует его в дерево запроса. Основное преимущество дерева запроса по сравнению с AST заключается в том, что многие компоненты будут разрешены, например, хранилище. Мы также знаем, из какой таблицы читать, алиасы также разрешены, и дерево знает различные используемые типы данных. С этими всеми преимуществами анализатор может применять оптимизации. Способ работы этих оптимизаций осуществляется через "проходы". Каждый проход будет искать различные оптимизации. Вы можете увидеть все проходы здесь, давайте посмотрим на это на практике, используя наш предыдущий запрос:
Между двумя исполнениями вы можете увидеть разрешение алиасов и проекций.
Планировщик
Планировщик берет дерево запроса и строит из него план запроса. Дерево запроса сообщает нам, что мы хотим сделать с конкретным запросом, а план запроса говорит нам, как мы это сделаем. Дополнительные оптимизации будут выполняться как часть плана запроса. Вы можете использовать EXPLAIN PLAN
или EXPLAIN
, чтобы увидеть план запроса (EXPLAIN
выполнит EXPLAIN PLAN
).
Хотя это дает нам некоторую информацию, мы можем получить больше. Например, возможно, мы хотим знать название столбца, по которому нам нужны проекции. Вы можете добавить заголовок к запросу:
Таким образом, теперь вы знаете имена столбцов, которые необходимо создать для последней проекции (minimum_date
, maximum_date
и percentage
), но вы также можете захотеть получить детали всех действий, которые необходимо выполнить. Вы можете сделать это, установив actions=1
.
Теперь вы можете видеть все входы, функции, алиасы и типы данных, которые используются. Вы можете увидеть некоторые оптимизации, которые планировщик собирается применить здесь.
Конвейер запросов
Конвейер запросов создается из плана запроса. Конвейер запросов очень похож на план запроса, с той разницей, что это не дерево, а граф. Он подчеркивает, как ClickHouse будет выполнять запрос и какие ресурсы будут использованы. Анализ конвейера запросов очень полезен, чтобы увидеть, где находится узкое место в терминах входов/выходов. Давайте возьмем наш предыдущий запрос и посмотрим на выполнение конвейера запросов:
Внутри скобок находится шаг плана запроса, а рядом с ним — процессор. Это отличная информация, но поскольку это граф, было бы неплохо визуализировать его в таком виде. У нас есть настройка graph
, которую мы можем установить в 1 и указать формат вывода как TSV:
Вы можете скопировать этот вывод и вставить здесь, и это создаст следующий график:

Белый прямоугольник соответствует узлу в конвейере, серый прямоугольник соответствует этапам плана запроса, а x
, за которым следует число, соответствует количеству входов/выходов, которые используются. Если вы не хотите видеть их в компактном виде, вы всегда можете добавить compact=0
:

Почему ClickHouse не читает из таблицы, используя несколько потоков? Давайте попробуем добавить больше данных в нашу таблицу:
Теперь давайте снова запустим наш запрос EXPLAIN
:

Таким образом, исполнитель решил не параллелить операции, потому что объем данных был недостаточно высок. Добавив больше строк, исполнитель, следовательно, решил использовать несколько потоков, как показано на графике.
Исполнитель
Наконец, последний шаг выполнения запроса выполняется исполнителем. Он берет конвейер запроса и выполняет его. Существуют различные типы исполнителей, в зависимости от того, выполняете ли вы SELECT
, INSERT
или INSERT SELECT
.