ClickHouse — наблюдаемость встроена в движокClickHouse — observability is built into the engine

МониторингMonitoring

В отличие от многих БД, где мониторинг — это внешний агент, парсящий логи, у ClickHouse почти вся observability доступна как обычные таблицы, опрашиваемые обычным `SELECT`. Здесь — какие таблицы за что отвечают, как вывести их наружу в Prometheus/Grafana, и на какие метрики ставить алерты в первую очередь.Unlike many DBs where monitoring is an external agent parsing logs, almost all of ClickHouse's observability is available as ordinary tables, queryable with a plain `SELECT`. Here's which tables cover what, how to export them to Prometheus/Grafana, and which metrics to alert on first.

частый вопросcommon interview question

Системные таблицы: обзорSystem tables: overview

Наблюдаемость встроена в сам движок: база `system` содержит десятки таблиц, часть из них — снимок текущего состояния (`system.parts`, `system.replicas`), часть — накопленная история (`system.query_log`, `system.part_log`), часть — просто счётчики (`system.metrics`). Это такие же таблицы ClickHouse, с тем же SQL — можно строить дашборды прямо поверх них без дополнительного слоя экспорта, хотя для интеграции с внешним мониторингом (следующий раздел) обычно всё же нужен экспортёр.Observability is built into the engine itself: the `system` database holds dozens of tables — some a snapshot of current state (`system.parts`, `system.replicas`), some accumulated history (`system.query_log`, `system.part_log`), some plain counters (`system.metrics`). These are ordinary ClickHouse tables with the same SQL — dashboards can be built directly on top of them without an extra export layer, though integrating with external monitoring (next section) usually still needs an exporter.

Таблицы для мониторинга производительностиTables for performance monitoring

таблицаtableчто показываетwhat it shows
system.query_logистория выполненных запросов: длительность, использованная память (`memory_usage`), прочитанные строки/байты, текст запроса и код ошибки — основной источник для поиска медленных или упавших запросов постфактум. По умолчанию пишется не мгновенно, а с задержкой сброса буфера — не ждите запрос в логе сразу после выполнения.history of executed queries: duration, memory used (`memory_usage`), rows/bytes read, query text, and error code — the primary source for finding slow or failed queries after the fact. Written with a buffer-flush delay by default, not instantly — don't expect a query to show up in the log right after it runs.
system.partsтекущий снимок кусков по каждой таблице — количество, суммарный размер, состояние (`active`). Растущее число активных кусков на таблице без остановки роста — ранний признак того, что фоновое слияние не успевает за вставками (см. "Too many parts" в архитектуре).a current snapshot of parts per table — count, total size, state (`active`). A growing number of active parts on a table with no leveling off is an early sign background merges aren't keeping up with inserts (see "Too many parts" in architecture).
system.mergesслияния кусков, выполняющиеся прямо сейчас — прогресс, объём читаемых/записываемых данных. Полезно, когда нужно понять, не "съедает" ли фоновое слияние диск/CPU в моменте, конкурируя с обслуживанием запросов.part merges running right now — progress, volume of data read/written. Useful for checking whether a background merge is currently eating disk/CPU, competing with query serving.
system.mutationsстатус выполнения `ALTER TABLE ... UPDATE/DELETE` — эти операции асинхронны (см. архитектуру) и могут выполняться долго; колонка `is_done`/`latest_fail_reason` показывает, завершилась ли мутация и не упала ли с ошибкой.execution status of `ALTER TABLE ... UPDATE/DELETE` — these operations are asynchronous (see architecture) and can run for a long time; the `is_done`/`latest_fail_reason` columns show whether a mutation finished or failed.
system.replicasсостояние репликации по каждой `ReplicatedMergeTree`-таблице: отставание (`absolute_delay`), количество кусков в очереди на репликацию, доступность Keeper-сессии. Ключевая таблица для обнаружения "отставшей" или "сломанной" реплики до того, как это заметят по факту стейл-чтений.replication state per `ReplicatedMergeTree` table: lag (`absolute_delay`), the number of parts queued for replication, Keeper session availability. The key table for catching a lagging or broken replica before stale reads reveal it in practice.
system.disks / system.parts (по columns)свободное место на каждом сконфигурированном диске/томе — включая холодный том, если настроен TTL MOVE (см. эксплуатацию). Прямой источник для алерта "диск скоро заполнится", учитывающий именно ClickHouse-специфичные тома, а не только `df` на уровне ОС.free space on each configured disk/volume — including the cold volume, if TTL MOVE is set up (see operations). A direct source for a "disk about to fill up" alert that accounts for ClickHouse-specific volumes, not just OS-level `df`.
system.metrics / system.asynchronous_metricsтекущее состояние сервера в моменте — активные соединения, потоки, размер очередей, использование памяти движками кэшей. Это то, что обычно экспортируется в Prometheus как gauge-метрики.current server state at this instant — active connections, threads, queue sizes, cache-engine memory use. This is typically what gets exported to Prometheus as gauge metrics.
-- топ-5 самых тяжёлых по памяти запросов за последний час-- top 5 heaviest queries by memory over the last hour
SELECT
    query,
    memory_usage,
    query_duration_ms,
    read_rows
FROM system.query_log
WHERE event_time > now() - INTERVAL 1 HOUR
  AND type = 'QueryFinish'
ORDER BY memory_usage DESC
LIMIT 5;

-- таблицы, приближающиеся к "Too many parts"-- tables approaching "Too many parts"
SELECT
    table,
    count() AS active_parts
FROM system.parts
WHERE active
GROUP BY table
ORDER BY active_parts DESC
LIMIT 10;

Интеграция с Prometheus/GrafanaPrometheus/Grafana integration

Встроенный `/metrics`-эндпоинт (включается в `config.d/` через ``) экспортирует `system.metrics`/`system.asynchronous_metrics`/`system.events` в формате, который Prometheus умеет скрейпить напрямую — не нужен отдельный exporter-процесс, как для многих других БД. Готовые Grafana-дашборды (официальный ClickHouse dashboard в grafana.com) закрывают базовый набор: нагрузка на CPU/память, скорость вставки, задержка запросов, отставание реплик.The built-in /metrics endpoint (enabled in config.d/ via <prometheus>) exports system.metrics/system.asynchronous_metrics/system.events in a format Prometheus can scrape directly — no separate exporter process needed, unlike many other DBs. Ready-made Grafana dashboards (the official ClickHouse dashboard on grafana.com) cover the basics: CPU/memory load, insert rate, query latency, replica lag.

Приоритет алертов на практике: отставание реплики (`system.replicas.absolute_delay` растёт без остановки — предвестник стейл-чтений или полного разрыва репликации), рост количества активных кусков (предвестник "Too many parts", останавливающего вставки), свободное место на горячем томе (предвестник полного отказа записи). Все три метрики предупреждают о проблеме за минуты-часы до того, как она станет отказом обслуживания — в отличие от, например, самого факта упавшего запроса, который уже произошёл.Alert priority in practice: replica lag (system.replicas.absolute_delay climbing without leveling off — a precursor to stale reads or a full replication break), a rising active-parts count (a precursor to "Too many parts" halting inserts), free space on the hot volume (a precursor to a full write failure). All three warn of trouble minutes to hours before it becomes an outage — unlike, say, a failed query itself, which has already happened.

ГраблиGotchas

system.query_log сам по себе может стать источником нагрузкиcan itself become a source of load

На высоконагруженном кластере `system.query_log` растёт очень быстро (запись в него — тот же `INSERT`, что и в обычные таблицы, с теми же ограничениями на частоту, см. эксплуатацию) — без настроенного TTL на этой таблице она сама может стать источником проблемы "много мелких кусков" или занять неожиданно много места на диске. Явный `TTL` на `system.query_log` (например, хранить 2 недели) — обязательная часть настройки мониторинга, не опция по умолчанию во всех версиях.On a heavily loaded cluster, `system.query_log` grows very fast (writing to it is the same kind of `INSERT` as to regular tables, with the same rate limits, see operations) — without a configured TTL on this table, it can itself become a source of the "many small parts" problem or take up unexpectedly much disk space. An explicit `TTL` on `system.query_log` (say, keep 2 weeks) is a mandatory part of monitoring setup, not a default in every version.

Разница между system.metrics (мгновенный снимок) и system.events (счётчик с момента старта)The difference between system.metrics (instant snapshot) and system.events (a counter since startup)

`system.metrics` показывает значение "прямо сейчас" (например, число активных соединений в этот момент), а `system.events` — монотонно растущий счётчик событий с момента запуска сервера (например, суммарное число выполненных запросов). Использование `system.events` как "текущей нагрузки" без вычисления разницы между двумя замерами по времени даёт бессмысленное всегда растущее число — для скорости (запросов/сек) нужна именно разница за интервал, что и делают экспортёры Prometheus через `rate()`.`system.metrics` shows a "right now" value (say, the number of active connections at this instant), while `system.events` is a monotonically increasing event counter since server startup (say, the total number of queries executed). Using `system.events` as "current load" without computing the difference between two time-spaced measurements gives a meaningless ever-growing number — a rate (queries/sec) needs the delta over an interval, which is exactly what Prometheus exporters do via `rate()`.