【列存引擎内核】Distributed 引擎与分布式查询路由

💡 原文中文,约18100字,阅读约需43分钟。
📝

内容提要

本文讨论了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 提供有限的分布式事务支持。

🏷️

标签

➡️

继续阅读