Database / Technology · 2022年10月9日

Clickhouse eats disk space

列数据库或者“分析型数据库”已经不是什么新鲜的事物了,比如AWS的Redshift,比如今天要谈到的Clickhouse。由于其数据存储方法专注于“列”,因此其先天就具有“统计快”的特点。

当然这篇博并不会展开说列数据库的优劣,那可能一写就得几万字…这篇博主要说明我在使用Clickhouse的时候发现的一个问题:硬盘使用率。

在基本同样的使用环境下,我发现mysql数据库和clickhouse数据的硬盘占用空间差距非常大,大约是1:3。我一度怀疑是不是因为列存储占用的空间就是大于行存储,但是转念一想,数据都那么多,只是链接方式不用罢了,不应该会有那么大的空间区别。

于是第一个操作就是要找出哪些table占用了大量的空间:(参考Altinity Knowledge Base的文章

SELECT
    database,
    table,
    formatReadableSize(sum(data_compressed_bytes) AS size) AS compressed,
    formatReadableSize(sum(data_uncompressed_bytes) AS usize) AS uncompressed,
    round(usize / size, 2) AS compr_rate,
    sum(rows) AS rows,
    count() AS part_count
FROM system.parts
WHERE (active = 1) AND (database LIKE '%') AND (table LIKE '%')
GROUP BY
    database,
    table
ORDER BY size DESC;

运行后发现,真正存储数据的table并没有占用太大的空间,相反地,system下的query_thread_log, query_log, trace_log, metric_log占用了非常大的空间,尤其是query_thread_log,1个TB。

参考Clickhouse的官方文档解释,这些log都是各有各的用途,默认也都是开启的。而且Clickhouse并不会自动地删除这些数据。所以在不调优的情况下,这些表是越来越大的,而且请求得越快,硬盘涨得也就越快。

所以必须对这些参数进行调优。主要思路有如下三种:

第一种,狠一点,直接掐断这个功能,即连表都不创建。

第二种,保留表,通过用户配置文件控制是否启用。

第三种,保留表并且持续启用,但是修改表的TTL值,让其周期性地过期。

我个人觉得混合使用这三种策略比较适合:

  • 对于没什么必要的表,直接掐断,比如metric_log, text_log, part_log之类,当然这里的“非必要”是因使用情况而异的,有些对debug要求非常大的使用场景下,很多表都是有价值表里的。
  • 对于query_log这个表,我认为很有必要保留。通过这个表可以很容易写一写query来判断数据库使用中的查询速度和具体使用情况。所以我建议对于query_log这个表,使用增加TTL的方法。
  • 对于query_thread_log这个“重度使用”的表,我建议保留其表的创建,但是默认disable。这个表提供了比query_log更详细的信息,如果需要特别debug时,可以通过配置文件打开。

具体的写法请参照Altinity Knowledge Base的这篇文章,我觉得写的非常清晰,这里就不再赘述了。