【列存引擎内核】Distributed 引擎与分布式查询路由
内容提要
本文讨论了ClickHouse的分布式表引擎,重点介绍了水平分片和跨节点查询的实现。内容包括分片键的选择、INSERT和SELECT的路由机制,以及与PostgreSQL Citus的区别。强调分布式表的主要作用是路由而非存储,并提供了DDL示例和集群配置细节,最后总结了最佳实践和常见反模式。
关键要点
-
ClickHouse 的 Distributed 引擎是查询与写入的路由层,而不是存储格式。
-
分布式表的主要作用是路由而非存储,所有列存文件格式遵循 MergeTree Part 格式。
-
分片键的选择影响 INSERT 目标 shard 和查询的局部性,推荐使用 cityHash64(user_id) 作为分片键。
-
INSERT 路由机制通过协调节点将数据按分片键分发到各个 shard。
-
SELECT 查询通过协调节点将请求下发到各个 shard 的本地表,并进行并行执行。
-
使用 GLOBAL IN 可以避免子查询在每个 shard 中执行,从而提高查询效率。
-
与 PostgreSQL Citus 的主要区别在于 ClickHouse 不支持跨 shard 的单事务和透明的 resharding。
-
最佳实践包括使用星型架构和复制维表,避免使用不当的分片键和 GLOBAL JOIN。
延伸解读
分片键的选择与影响
分片键在 ClickHouse 的 Distributed 引擎中起着至关重要的作用。选择合适的分片键不仅影响数据的均匀分布,还直接关系到查询的性能。推荐使用 cityHash64(user_id) 作为分片键,以确保用户级查询的局部性,避免超大用户热点导致的性能瓶颈。
INSERT 路由机制的优化
在 ClickHouse 中,INSERT 操作通过协调节点将数据按分片键分发到各个 shard。为了提高写入效率,建议使用批量插入,避免小批量频繁写入导致的过多小部分(small parts)问题。此外,使用 async_insert 可以进一步提升写入性能。
GLOBAL IN 与查询性能
使用 GLOBAL IN 可以有效避免在每个 shard 中执行子查询,从而提高查询效率。然而,这也可能导致协调节点成为内存瓶颈,尤其是在处理大维表时。因此,在设计查询时需谨慎使用 GLOBAL IN,确保协调节点的内存资源充足。
延伸问答
ClickHouse 的 Distributed 引擎主要功能是什么?
ClickHouse 的 Distributed 引擎主要用于查询与写入的路由,而不是存储数据。
如何选择分片键以优化查询性能?
推荐使用 cityHash64(user_id) 作为分片键,以提高用户级查询的局部性。
INSERT 操作是如何在 ClickHouse 的分布式表中路由的?
INSERT 操作通过协调节点计算每行的分片表达式,并将数据按分片分组后发送到各个 shard。
ClickHouse 的 SELECT 查询是如何执行的?
SELECT 查询通过协调节点将请求下发到各个 shard 的本地表,并进行并行执行。
GLOBAL IN 语句的使用场景是什么?
GLOBAL IN 适用于小子表未复制到各 shard 的情况,可以避免在每个 shard 中执行子查询。
ClickHouse 的 Distributed 引擎与 PostgreSQL Citus 有何不同?
ClickHouse 不支持跨 shard 的单事务和透明的 resharding,而 PostgreSQL Citus 提供有限的分布式事务支持。