ClickHouse — наблюдаемость встроена в движокClickHouse — observability is built into the engine
В отличие от многих БД, где мониторинг — это внешний агент, парсящий логи, у 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.
Наблюдаемость встроена в сам движок: база `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.
| таблица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;
Встроенный `/metrics`-эндпоинт (включается в `config.d/` через `/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.
На высоконагруженном кластере `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` — монотонно растущий счётчик событий с момента запуска сервера (например, суммарное число выполненных запросов). Использование `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()`.