Перейти к основному содержанию
В ClickHouse работает выборочный профилировщик, который позволяет анализировать выполнение запросов. С его помощью можно найти процедуры в исходном коде, которые чаще всего используются во время выполнения запроса. Вы можете отслеживать затраченное время CPU и реальное время, включая время простоя. Профилировщик запросов автоматически включен в ClickHouse Cloud. Следующий пример запроса находит наиболее частые трассировки стека для профилируемого запроса с разрешенными именами функций и указанием их расположения в исходном коде:
Замените значение query_id на ID запроса, который вы хотите профилировать.
В ClickHouse Cloud ID запроса можно получить, нажав ”…” в крайней правой части панели над таблицей результатов запроса (рядом с переключателем table/chart). Откроется контекстное меню, в котором можно нажать “Copy query ID”.Используйте clusterAllReplicas(default, system.trace_log), чтобы выбрать данные со всех узлов cluster:
SELECT
    count(),
    arrayStringConcat(arrayMap(x -> concat(demangle(addressToSymbol(x)), '\n    ', addressToLine(x)), trace), '\n') AS sym
FROM clusterAllReplicas(default, system.trace_log)
WHERE query_id = '<query_id>' AND trace_type = 'CPU' AND event_date = today()
GROUP BY trace
ORDER BY count() DESC
LIMIT 10
SETTINGS allow_introspection_functions = 1

Использование профилировщика запросов в самоуправляемых развертываниях

Чтобы использовать профилировщик запросов в самоуправляемых развертываниях, выполните следующие шаги:
1

Установите ClickHouse с отладочной информацией

Установите пакет clickhouse-common-static-dbg:
  1. Следуйте инструкциям из шага “Настройте Debian-репозиторий”
  2. Выполните sudo apt-get install clickhouse-server clickhouse-client clickhouse-common-static-dbg, чтобы установить скомпилированные бинарные файлы ClickHouse с отладочной информацией
  3. Выполните sudo service clickhouse-server start, чтобы запустить сервер
  4. Выполните clickhouse-client. Отладочные символы из clickhouse-common-static-dbg будут автоматически подхвачены сервером — ничего дополнительно включать не нужно
2

Проверьте конфигурацию сервера

Убедитесь, что раздел trace_log в вашем файле конфигурации сервера настроен. По умолчанию он включен:
<!-- Журнал трассировки. Хранит трассировки стека, собранные профилировщиками запросов.
     См. настройки query_profiler_real_time_period_ns и query_profiler_cpu_time_period_ns. -->
<trace_log>
    <database>system</database>
    <table>trace_log</table>

    <partition_by>toYYYYMM(event_date)</partition_by>
    <flush_interval_milliseconds>7500</flush_interval_milliseconds>
    <max_size_rows>1048576</max_size_rows>
    <reserved_size_rows>8192</reserved_size_rows>
    <buffer_size_rows_flush_threshold>524288</buffer_size_rows_flush_threshold>
    <!-- Указывает, следует ли сбрасывать журналы на диск в случае сбоя -->
    <flush_on_crash>false</flush_on_crash>
    <symbolize>true</symbolize>
</trace_log>
Этот раздел настраивает системную таблицу trace_log, содержащую результаты работы профилировщика. Помните, что данные в этой таблице актуальны только для работающего сервера. После перезапуска сервера ClickHouse не очищает таблицу, и все сохраненные адреса виртуальной памяти могут стать недействительными.
3

Настройте таймеры профилирования

Настройте параметры query_profiler_cpu_time_period_ns или query_profiler_real_time_period_ns. Оба параметра можно использовать одновременно.Эти параметры позволяют настроить таймеры профилировщика. Поскольку это настройки сеанса, вы можете задать разную частоту сэмплирования для всего сервера, отдельных пользователей или профилей пользователей, для интерактивного сеанса и для каждого отдельного запроса.Частота сэмплирования по умолчанию — один сэмпл в секунду, при этом включены таймеры CPU и реального времени. Такая частота позволяет собирать достаточно информации о кластере ClickHouse, не влияя на производительность сервера. Если вам нужно профилировать каждый отдельный запрос, используйте более высокую частоту сэмплирования.
4

Проанализируйте системную таблицу trace_log

Чтобы анализировать системную таблицу trace_log, разрешите функции интроспекции с помощью настройки allow_introspection_functions:
SET allow_introspection_functions=1
По соображениям безопасности функции интроспекции по умолчанию отключены
Используйте функции интроспекции addressToLine, addressToLineWithInlines, addressToSymbol и demangle, чтобы получить имена функций и их расположение в коде ClickHouse. Чтобы получить профиль для какого-либо запроса, нужно агрегировать данные из таблицы trace_log. Вы можете агрегировать данные по отдельным функциям или по всей трассировке стека.
Если вам нужно визуализировать данные из trace_log, попробуйте флеймграф и speedscope.

Построение флеймграфов с помощью функции flameGraph

ClickHouse предоставляет агрегатную функцию flameGraph, которая строит флеймграф напрямую по трассировкам стека, хранящимся в trace_log. На выходе получается массив строк в формате, совместимом с flamegraph.pl. Синтаксис:
flameGraph(traces, [size = 1], [ptr = 0])
Аргументы:
  • traces — стектрейс. Array(UInt64).
  • size — размер выделения для профилирования памяти. Int64.
  • ptr — адрес выделенной памяти. UInt64.
Если ptr не равен нулю, flameGraph сопоставляет выделения (size > 0) и освобождения (size < 0) с одинаковыми размером и указателем. Отображаются только выделения, которые не были освобождены. Несопоставленные освобождения игнорируются.

CPU-флеймграф

Для выполнения приведённых ниже запросов у вас должен быть установлен flamegraph.pl.Для этого выполните:
git clone https://github.com/brendangregg/FlameGraph
# Затем используйте его так:
# ~/FlameGraph/flamegraph.pl
В следующих запросах замените flamegraph.pl на путь к файлу flamegraph.pl на вашей машине
SET query_profiler_cpu_time_period_ns = 10000000;
Выполните запрос, затем постройте флеймграф:
clickhouse client --allow_introspection_functions=1 \
    -q "SELECT arrayJoin(flameGraph(arrayReverse(trace)))
        FROM system.trace_log
        WHERE trace_type = 'CPU' AND query_id = '<query_id>'" \
    | flamegraph.pl > flame_cpu.svg

Флеймграф памяти — все выделения

SET memory_profiler_sample_probability = 1, max_untracked_memory = 1;
Выполните запрос, затем постройте флеймграф:
clickhouse client --allow_introspection_functions=1 \
    -q "SELECT arrayJoin(flameGraph(trace, size))
        FROM system.trace_log
        WHERE trace_type = 'MemorySample' AND query_id = '<query_id>'" \
    | flamegraph.pl --countname=bytes --color=mem > flame_mem.svg

Флеймграф памяти — неосвобождённые выделения

Этот вариант сопоставляет выделения памяти с освобождениями по указателю и показывает только ту память, которая не была освобождена во время запроса.
SET memory_profiler_sample_probability = 1, max_untracked_memory = 1,
    use_uncompressed_cache = 1,
    merge_tree_max_rows_to_use_cache = 100000000000,
    merge_tree_max_bytes_to_use_cache = 1000000000000;
Выполните следующий запрос, чтобы построить флеймграф:
clickhouse client --allow_introspection_functions=1 \
    -q "SELECT arrayJoin(flameGraph(trace, size, ptr))
        FROM system.trace_log
        WHERE trace_type = 'MemorySample' AND query_id = '<query_id>'" \
    | flamegraph.pl --countname=bytes --color=mem > flame_mem_unfreed.svg

Флеймграф памяти — активные выделения на определённый момент времени

Этот подход позволяет определить пиковое потребление памяти и визуализировать, что было выделено в этот момент.
SET memory_profiler_sample_probability = 1, max_untracked_memory = 1;

Определите использование памяти во времени

SELECT
    event_time,
    formatReadableSize(max(s)) AS m
FROM (
    SELECT
        event_time,
        sum(size) OVER (ORDER BY event_time) AS s
    FROM system.trace_log
    WHERE query_id = '<query_id>' AND trace_type = 'MemorySample'
)
GROUP BY event_time
ORDER BY event_time;

Найдите момент времени, в который использование памяти было максимальным

SELECT
    argMax(event_time, s),
    max(s)
FROM (
    SELECT
        event_time,
        sum(size) OVER (ORDER BY event_time) AS s
    FROM system.trace_log
    WHERE query_id = '<query_id>' AND trace_type = 'MemorySample'
);

Постройте флеймграф активных выделений в этот момент времени

clickhouse client --allow_introspection_functions=1 \
    -q "SELECT arrayJoin(flameGraph(trace, size, ptr))
        FROM (
            SELECT * FROM system.trace_log
            WHERE trace_type = 'MemorySample'
              AND query_id = '<query_id>'
              AND event_time <= '<time_point>'
            ORDER BY event_time
        )" \
    | flamegraph.pl --countname=bytes --color=mem > flame_mem_time_point_pos.svg

Постройте флеймграф освобождений памяти после этого момента времени (чтобы понять, что было освобождено позже)

clickhouse client --allow_introspection_functions=1 \
    -q "SELECT arrayJoin(flameGraph(trace, -size, ptr))
        FROM (
            SELECT * FROM system.trace_log
            WHERE trace_type = 'MemorySample'
              AND query_id = '<query_id>'
              AND event_time > '<time_point>'
            ORDER BY event_time DESC
        )" \
    | flamegraph.pl --countname=bytes --color=mem > flame_mem_time_point_neg.svg

Пример

Фрагмент кода ниже:
  • Фильтрует данные trace_log по идентификатору запроса и текущей дате.
  • Выполняет агрегацию по трассировке стека.
  • Использует функции интроспекции, чтобы получить отчет о:
    • Именах символов и соответствующих им функциях исходного кода.
    • Расположении этих функций в исходном коде.
SELECT
    count(),
    arrayStringConcat(arrayMap(x -> concat(demangle(addressToSymbol(x)), '\n    ', addressToLine(x)), trace), '\n') AS sym
FROM system.trace_log
WHERE (query_id = '<query_id>') AND (event_date = today())
GROUP BY trace
ORDER BY count() DESC
LIMIT 10
Последнее изменение 10 июня 2026 г.