ClickHouse中使用分区键优化JOIN 实现类似亲和性共置的分布式关联
ClickHouse亲和性共置JOIN实现方案
前提修正
首先需要纠正一个配置误区:分区键仅控制单节点内部的数据拆分规则,不负责跨节点的数据分片分布,要实现和Apache Ignite一致的亲和性共置,需要先保证以下配置正确:
- 两张表对应的分布式表归属同一个ClickHouse集群
- Employee表对应的分布式表分片键设置为
ID,Attendance表对应的分布式表分片键设置为Employee_ID - 两张分布式表使用完全相同的分片规则(如均使用
cityHash64计算分片、集群分片总数一致),确保相同ID的员工数据和对应考勤数据始终落在同一个分片节点上。
两种实现方案
方案一:自动优化本地JOIN(21.8及以上版本支持)
执行查询前先开启两个会话优化参数,ClickHouse会自动识别共置的分片规则,直接在每个节点本地完成JOIN后汇总结果,不需要跨节点拉取数据:
SET distributed_joins_use_own_sharding_key = 1; SET optimize_skip_unused_shards = 1;
之后直接写关联查询即可,关联键必须为两张表的分片键:
SELECT e.ID, e.Name, a.Date, a.isPresent FROM distributed_employee e INNER JOIN distributed_attendance a ON e.ID = a.Employee_ID;
方案二:手动下发本地计算(全版本兼容)
如果需要更可控的执行逻辑,或是使用21.8之前的旧版本,可以直接通过集群查询将计算逻辑下发到每个节点本地执行,再合并结果:
SELECT * FROM cluster( '替换为你的集群名称', 'default', ' SELECT e.ID, e.Name, a.Date, a.isPresent FROM employee_local e INNER JOIN attendance_local a ON e.ID = a.Employee_ID ' );
其中employee_local、attendance_local为节点上存储的本地MergeTree表名,该语句会直接在每个分片节点执行本地表JOIN,仅返回最终结果到发起查询的节点合并。
之前方案失效原因说明
- GLOBAL JOIN会先将右表全量拉取到发起查询的节点,再分发到所有分片,完全不利用共置特性
- 未开启优化参数的普通LOCAL JOIN默认不会识别分片键共置规则,仍会跨节点拉取关联需要的数据
内容的提问来源于stack exchange,提问作者Vineeth Mohan
相关产品推荐
相关产品推荐

