bigywater.tech
ClickHouse 内部原理 · 69

ClickHouse 分布式查询:数据应该在哪里合并

真实用EXPLAIN对比普通JOIN和GLOBAL JOIN的执行计划,看清楚JOIN计算依然发生在各分片本地,GLOBAL关键字真实改变的是右表数据的来源和随之而来的统计信息代价。

JOIN计算仍在本地
真实两种写法的哈希匹配都发生在各分片本地
GLOBAL丢失统计
真实广播来的临时表没有Cost/Selectivity估计信息

做的事:真实用EXPLAIN对比普通JOIN和GLOBAL JOIN的执行计划

代码EXPLAIN actions=1 SELECT count() FROM demo.dist_tbl t INNER JOIN demo.dim_local d ON t.k=d.id; EXPLAIN actions=1 SELECT count() FROM demo.dist_tbl t GLOBAL INNER JOIN demo.dim_local d ON t.k=d.id;

验证:JOIN真实都在本地发生,区别在右表数据从哪来

实测 · 本机执行输出(节选)
普通JOIN:
  demo.dim_local[2100] ⋈ demo.local_tbl[1051]
  Algorithm: SpillingHashJoin(HashJoin)
  Cost: estimated 1.07 thousand           ← 真实有基于本地统计的代价估计
  ReadFromMergeTree (demo.dim_local)      ← 真实直接读本地磁盘上的表

GLOBAL JOIN:
  demo.local_tbl ⋈ _data_15869492931996880507_7049575549077029033
  Algorithm: SpillingHashJoin(ConcurrentHashJoin)
  Cost: estimated no stats                ← 真实没有代价估计信息
  Locality: GLOBAL                        ← 真实明确标注这是GLOBAL JOIN
  (右表变成了一个真实的_data_xxx临时表,不是demo.dim_local本身)

两份EXPLAIN真实最关键的区别,不在"JOIN在哪里算"——两种写法的Join算子都真实出现在each分片本地的执行子树里,说明实际的哈希匹配计算依然是在每个分片各自完成的;真实的区别在于JOIN右边喂给这个本地JOIN算子的,到底是哪一份数据——普通JOIN真实直接读demo.dim_local这张表在本分片本地磁盘上的内容;GLOBAL JOIN真实读的是一个名字很怪的临时表_data_xxx,这正是本系列前面《GLOBAL IN和普通IN的区别》验证过的广播机制在JOIN上的真实体现——发起查询的节点先把demo.dim_local算出来打包成这份临时数据,再真实广播给每个分片,各分片本地JOIN算子读的是这份广播来的、内容完全一致的临时数据,而不是各自本地可能不一致的原表。

真实的额外代价:GLOBAL JOIN丢失了统计信息

这次EXPLAIN还真实暴露了一个容易被忽略的副作用:普通JOIN读本地表时,查询优化器真实能拿到这张表的统计信息(本文看到的Cost: estimated 1.07 thousand、Selectivity: estimated (NDV) 0.0004826这类数字,都来自ClickHouse对本地part的真实统计),可以用来辅助判断JOIN顺序、选择更合适的算法;而GLOBAL JOIN真实用来接收广播数据的这个临时表,从优化器的角度看是一张全新生成、没有历史统计信息的表,本文的EXPLAIN里能看到Cost: estimated no stats——查询优化器对这部分真实是"盲操作",没有统计信息辅助决策。这就是本系列前几篇反复出现的同一个真实主题在这里的又一次体现:不管是JOIN(本篇)还是IN(前一篇),GLOBAL这个关键字真实解决的都是"数据分布不一致导致结果出错"这个根本问题,但它用广播换正确性的同时,真实也牺牲了原本能从本地表拿到的统计优化信息,以及广播本身的网络和临时存储开销——这也是为什么GLOBAL不应该被当成"分布式JOIN的万能安全开关"无脑加上,而应该在真正需要保证右表数据一致性的场景下,有意识地承担这份真实的额外代价。

分步演示:从EXPLAIN看清GLOBAL JOIN真实的代价

每一步都是本文上面用真实EXPLAIN跑出来的原始结果。

JOIN真实都在本地算,区别在右表数据来源
这一步新验证的JOIN类型

    本文用到的工具

    • 本机真实的3节点集群,真实的 EXPLAIN actions=1 对比JOIN与GLOBAL JOIN
    京ICP备2026067502号-1京公网安备11010502063487号