Flamegraph из system.trace_log
query_log отвечает на вопрос “что потребляет ресурсы”. Для ответа на “где именно в коде” нужен профилировщик. ClickHouse имеет встроенный sampling profiler, который регулярно делает snapshot стека вызовов (callstack) всех активных потоков и записывает их в system.trace_log. Агрегация этих snapshot в flamegraph позволяет визуально выявить CPU и Memory hotspots.
Workflow профилирования
system.trace_log: структура таблицы
-- Структура записей в trace_log
DESCRIBE system.trace_log;
-- Ключевые поля:
-- query_id String -- ID запроса (из system.query_log)
-- trace_type Enum -- CPU / Real / Memory / MemorySample
-- trace Array(UInt64) -- callstack: адреса функций
-- timestamp DateTime64 -- время snapshot
-- thread_id UInt64 -- ID потока
Типы трассировки:
| trace_type | Что профилирует | Когда использовать |
|---|---|---|
CPU | Время CPU (user space) | CPU-heavy вычисления, горячие функции |
Real | Реальное время (wall clock) | I/O ожидания, lock contention |
Memory | Выделение памяти | Memory-heavy операции |
MemorySample | Выборочный sampling памяти | Долгосрочный мониторинг памяти |
flameGraph(): встроенная функция агрегации
Функция flameGraph() добавлена в ClickHouse 23.x. Она принимает callstack из trace_log и возвращает текст в формате collapsed stacks:
-- Генерация flamegraph для конкретного запроса
SELECT flameGraph(trace, type)
FROM system.trace_log
WHERE query_id = 'ваш-query-id-здесь'
AND trace_type IN ('CPU', 'Real', 'Memory');
Практический workflow:
-- Шаг 1: Включить profiler с частотой 100 мс
SET query_profiler_real_time_period_ns = 100000000;
-- Шаг 2: Выполнить тяжёлый запрос
SELECT /* ваш тяжёлый запрос */ ...;
-- Шаг 3: Получить query_id последнего запроса
SELECT query_id
FROM system.query_log
WHERE type = 'QueryFinish'
AND user = currentUser()
ORDER BY event_time DESC
LIMIT 1;
-- Шаг 4: Сгенерировать flamegraph
SELECT flameGraph(trace, type)
FROM system.trace_log
WHERE query_id = '<полученный query_id>'
AND trace_type = 'CPU';
Вывод функции — текст в формате funcA;funcB;funcC 42, где 42 — число samples. Этот формат совместим с Brendan Gregg’s flamegraph.pl и большинством современных flamegraph-визуализаторов.
Jemalloc per-query profiling
Для детального профилирования памяти используйте jemalloc allocator profiling (доступно в ClickHouse 25.10+):
-- Включить per-query jemalloc profiling
SET jemalloc_enable_profiler = 1;
SET jemalloc_collect_profile_samples_in_trace_log = 1;
-- Выполнить memory-heavy запрос
SELECT /* запрос с большим потреблением памяти */
FROM huge_table
GROUP BY ...;
После выполнения в system.trace_log появятся записи с trace_type = 'MemorySample' от jemalloc. Их можно использовать в flameGraph() аналогично CPU traces:
SELECT flameGraph(trace, type)
FROM system.trace_log
WHERE query_id = '<query_id>'
AND trace_type = 'MemorySample';
system.processor_profile_log: детальный уровень процессоров
Для детального профилирования на уровне процессоров PIPELINE используйте system.processor_profile_log:
SELECT
processor_name,
sum(elapsed_us) AS total_us,
sum(input_rows) AS input_rows,
sum(output_rows) AS output_rows
FROM system.processor_profile_log
WHERE query_id = '<query_id>'
GROUP BY processor_name
ORDER BY total_us DESC;
Это позволяет выяснить, какой конкретный процессор в DAG (AggregatingTransform, MergeTreeSelect, FilterTransform) тратит больше всего времени.
clickhouse-flamegraph: внешний инструмент
Помимо встроенной flameGraph() функции, существует внешний OSS-инструмент clickhouse-flamegraph:
Установка:
# Через pip (Python CLI)
pip install clickhouse-flamegraph
# Или скачать бинарный релиз с GitHub:
# https://github.com/Slach/clickhouse-flamegraph
Использование:
clickhouse-flamegraph \
--query-id "ваш-query-id" \
--host "localhost" \
--trace-type "CPU" \
--output flamegraph.html
Отличия от встроенной flameGraph():
| Аспект | Встроенная flameGraph() | clickhouse-flamegraph CLI |
|---|---|---|
| Интеграция | Прямо в SQL | Внешняя CLI утилита |
| Вывод | Текст (collapsed stacks) | HTML/SVG файл с интерактивностью |
| Зависимости | Нет (встроена) | Python / бинарный релиз |
| Использование | SQL-запрос | CLI команда |
| Рекомендация | Для server-side pipeline | Для интерактивного анализа |
Ключевые выводы
- Sampling profiler делает snapshot стека вызовов каждые
query_profiler_real_time_period_nsнаносекунд — по умолчанию отключён. Включайте только для профилируемых запросов. flameGraph(trace, type)— встроенная aggregate function (23.x+), возвращает collapsed stacks из system.trace_log. Не требует внешних зависимостей.trace_type = 'CPU'— CPU hotspots;trace_type = 'Real'— включает I/O и lock ожидания. Для memory-heavy запросов используйтеjemalloc_enable_profiler = 1.system.processor_profile_logдаёт детальный breakdown по процессорам PIPELINE: видно, какой процессор тратит больше всего времени.- clickhouse-flamegraph CLI генерирует интерактивный HTML/SVG — удобно для визуального анализа с коллегами.