线上一台 ClickHouse 跑了两个月,磁盘吃掉几十 GB。查一下:
SELECT database, table,
formatReadableSize(sum(bytes)) AS size,
sum(rows) AS rows
FROM system.parts
WHERE active
GROUP BY database, table
ORDER BY sum(bytes) DESC
LIMIT 10;
结果:
system text_log 34.15 GiB 9亿行
system trace_log 11.41 GiB 5亿行
system asynchronous_metric_log 9.36 GiB 347亿行
system metric_log 7.75 GiB 3600万行
system part_log 4.65 GiB 6800万行
system query_log 3.59 GiB 3800万行
几乎全是 ClickHouse 自己写的内部监控日志。业务数据加起来才几个 G。
第一步:立刻清理
TRUNCATE 把大头清空:
TRUNCATE TABLE system.text_log;
TRUNCATE TABLE system.trace_log;
TRUNCATE TABLE system.asynchronous_metric_log;
TRUNCATE TABLE system.metric_log;
TRUNCATE TABLE system.part_log;
TRUNCATE TABLE system.processors_profile_log;
-- query_log 可以选择保留,用于事后排查
TRUNCATE TABLE system.latency_log;
query_log 是”这个 ClickHouse 都处理过什么 SQL”的记录,日常排查很有用,多数情况留着。
清完之后:
SYSTEM FLUSH LOGS;
再查一次磁盘:
du -sh /var/lib/clickhouse/data/system/*
空间没立刻回收是正常的。因为:
- MergeTree 的 parts 只是标记删除,等 merge
- 文件系统 cache
- delete_from_disk 有 TTL
可以强制一下:
OPTIMIZE TABLE system.query_log FINAL;
或者最粗暴:
sudo systemctl restart clickhouse-server
启动时会跳过被标记删除的 parts。
第二步:从根源关掉不需要的日志
清了以后不管,几周后又长回来。要真省心就编辑 config,把不用的日志表直接关掉。
编辑:
sudo nano /etc/clickhouse-server/config.d/logs.xml
内容:
<clickhouse>
<!-- 关掉巨吃磁盘的三个 -->
<text_log remove="1"/>
<trace_log remove="1"/>
<asynchronous_metric_log remove="1"/>
<metric_log remove="1"/>
<part_log remove="1"/>
<processors_profile_log remove="1"/>
<!-- query_log 保留,但缩短 TTL -->
<query_log>
<database>system</database>
<table>query_log</table>
<partition_by>toYYYYMM(event_date)</partition_by>
<ttl>event_date + INTERVAL 7 DAY DELETE</ttl>
<flush_interval_milliseconds>7500</flush_interval_milliseconds>
</query_log>
</clickhouse>
remove="1"直接不启用这类表<ttl>让 ClickHouse 自动过期删除老数据
重启生效:
sudo systemctl restart clickhouse-server
为什么这些表会爆
asynchronous_metric_log 每秒都在采几百个指标,一天几千万行是正常的。trace_log 记录每个 query 的 profile 事件,非常细。这些表默认全开,对于开发/测试很有用,对生产就是纯磁盘杀手。
生产环境的经验:
- 保留:
query_log(+ 7 天 TTL) - 可选保留:
query_thread_log排查慢查询用 - 关掉:
text_log、trace_log、asynchronous_metric_log、metric_log、part_log、processors_profile_log
如果需要采指标,用 Prometheus 拉 /metrics 接口,别依赖 ClickHouse 内部 metric_log。
顺手加个磁盘水位报警
SELECT
name,
formatReadableSize(free_space) AS free,
formatReadableSize(total_space) AS total,
round(free_space / total_space * 100, 1) AS free_percent
FROM system.disks;
低于 20% 该发告警了。
一句话总结
ClickHouse 磁盘被吃是 system.*_log 表的锅。先 TRUNCATE 清空、再 config 里 remove="1" 关掉大部分、给 query_log 加个 TTL。生产上从第一天就该这么配。
