先抛出三个问题:
- ClickHouse执行多分片聚合一定会比单机慢吗?
- 如果慢,那么会慢在哪里?
- 是否可以优化?
在20版本之前不支持explain语句,所以这里列举用explain和trace级别日志两种查看执行过程的方法。
这里以本地表和分布式表为例进行分析。集群配置了两分片,这里进行单机和集群查询的执行过程分析。
因为真实sql涉及机密,这里做了脱敏处理,后面不再赘述
explain
这种最简单,直接在sql语句前面增加explain,
查询本地表
explain
SELECT id,max(ch_updatetime) AS ch_updatetime_max
FROM database.merge_tree_table
GROUP BY id
输出
实际执行时间消耗12.7s,内存使用2.39G,每秒处理1167万行
查询分布式表
explain
SELECT id,max(ch_updatetime) AS ch_updatetime_max
FROM database.distributed_table
GROUP BY id
输出
实际执行时间消耗51s,内存使用5G左右,每秒处理581万行
这两者对比一下,区别主要是在MergingAggregated操作。
MergingAggregated真的有那么耗时吗?ClickHouse相当于超跑的话,做聚合为什么会慢4倍这么多?
trace级别日志
explain毕竟只是“花架子”,真正还要看实际执行的操作。这里把第二次查询分布式表的trace级别日志拿出来分析,关键日志如下:
[ch01] 2020.09.24 10:09:51.064623 [ 30751 ] {
22de5c9b-2df4-4251-b0c7-0ec77dcb1f67} <Debug> executeQuery: (from [::1]:46550) SELECT id,max(ch_updatetime) AS ch_updatetime_max FROM database.merge_tree_table GROUP BY settlementid
...
[ch02] 2020.09.24 10:09:51.069320 [ 71302 ] {
5b1ffeea-9d02-4a9c-8cdf-94c5457533e1} <Trace> ContextAccess (default): Access granted: SELECT(id, ch_updatetime) ON database.merge_tree_table
[ch02] 2020.09.24 10:09:51.070980 [ 71302 ] {
5b1ffeea-9d02-4a9c-8cdf-94c5457533e1} <Trace> database.merge_tree_table(SelectExecutor): Reading approx. 147587338 rows<