分步说明:ClickHouse 如何并行处理聚合查询
将工作分配到各处理通道
n 个并行的处理通道中,这些通道会将数据按块流式传输并逐块处理,最终得到结果:
n 个并行处理通道的数量由 max_threads 设置控制,默认情况下,该值与服务器上 ClickHouse 可用的单个 CPU 的核心数 (线程数) 相同。在上面的示例中,我们假设有 4 个核心。
在一台具有 8 个核心的机器上,查询处理吞吐量大致会翻倍 (但内存占用也会相应增加) ,因为会有更多通道并行处理数据:
高效的通道分配是最大化 CPU 利用率并缩短总查询时间的关键。
在分片表上处理查询
最先接收到查询的服务器会收集各个分片返回的所有子结果,并将其合并为最终的全局结果。 将查询负载分散到各个分片上,可以横向扩展并行能力,尤其适用于高吞吐量环境。
ClickHouse Cloud 使用并行副本,而不是分片在 ClickHouse Cloud 中,同样的并行能力是通过并行副本实现的,其工作方式与无共享集群中的分片类似。每个 ClickHouse Cloud 副本——也就是一个无状态计算节点——都会并行处理一部分数据,并像独立分片一样共同形成最终结果。
监控查询并行度
- ① ClickHouse 需要在 3 个数据范围内读取 3,609 个粒度 (在跟踪日志中记为标记) 。
- ② 借助 59 个 CPU 核心,它会将这项工作分配到 59 个并行处理流中——每个处理通道对应一个流。
× 59 的算子会在 59 条并行处理通道上,对互不重叠的数据区域并发执行。这反映了 max_threads 的值,也展示了查询的各个阶段如何在 CPU 核心之间实现并行化。
ClickHouse 的嵌入式 web UI (可通过 /play 端点访问) 可以将上面的物理计划渲染为图形化视图。在此示例中,我们将 max_threads 设置为 4,以使可视化更紧凑,因此只显示 4 条并行处理通道:
注意:请从左到右阅读该可视化图。每一行代表一条并行处理通道,数据以数据块为单位流式传输,并依次应用过滤、聚合和最终处理等转换。在这个示例中,你可以看到与 max_threads = 4 设置对应的四条并行通道。
跨处理通道的负载均衡
Resize 算子会在各处理通道之间对数据块流进行重新分区和重新分发,以保持各通道的负载均衡。当不同数据范围中满足查询谓词的行数差异较大时,这种重新平衡尤为重要;否则,某些通道可能负载过高,而其他通道则处于空闲状态。通过重新分配工作,较快的通道实际上可以帮助较慢的通道分担负载,从而优化整体查询运行时间。
为什么 max_threads 并不总会生效
n 条并行处理通道的数量由 max_threads 设置控制,默认情况下,它与服务器上 ClickHouse 可用的 CPU 核心数一致:
max_threads 的值可能会被忽略,这取决于所选待处理数据量的多少:
max_threads 设置为 59,ClickHouse 在扫描数据时仍只使用了 30 个并发流。
现在来运行这个查询:
max_threads 配置为多少,ClickHouse 只有在数据量足以支撑时,才会分配额外的并行处理通道。max_threads 中的 “max” 表示上限,并不意味着一定会使用这么多线程。
这里“足够的数据”主要由两个设置决定:它们定义了每个处理通道需要处理的最小行数 (默认 163,840) 和最小字节数 (默认 2,097,152) :
对于 shared-nothing 集群:
对于使用共享存储的集群 (例如 ClickHouse Cloud) :
- merge_tree_min_rows_for_concurrent_read_for_remote_filesystem
- merge_tree_min_bytes_for_concurrent_read_for_remote_filesystem
max_threads。
这说明,对于小型数据集上的查询,ClickHouse 会主动限制并发度。设置覆盖仅应用于测试,不要用于生产环境,因为这可能导致执行效率低下或资源争用。
关键要点
- ClickHouse 使用与
max_threads关联的处理通道并行执行查询。 - 实际通道数量取决于选中待处理数据的规模。
- 使用
EXPLAIN PIPELINE和跟踪日志分析通道使用情况。
在哪里查找更多信息
- 查询处理层 – VLDB 2024 论文 (网页版) - 详细解析 ClickHouse 的内部执行模型,包括调度、流水线处理和算子设计。
- 部分聚合状态详解 - 从技术角度深入讲解部分聚合状态如何在各条处理通道中实现高效的并行执行。
- 一段详细讲解 ClickHouse 查询处理全过程的视频教程: