首页/数据/NoSQL 速查/JOIN 与连接策略
ClickHouse56 条

JOIN 与连接策略

ClickHouse JOIN 支持 INNER/LEFT/RIGHT/FULL 与 ASOF、ANY 等变体:右表通常加载进内存,把小表放右边、大表放左边更省资源。

NoSQL 速查数据更新于 2026-10-13

ClickHouse JOIN 的特点

ClickHouse 的 JOIN 支持 INNER、LEFT、RIGHT、FULL 以及按时间就近匹配的 ASOF,还有只取一行的 ANY 变体。它的执行方式与关系库不同:右表通常会被加载进内存再做匹配,所以「小表放右边、大表放左边」是控制资源的主要手段;分布式表上还要分清本地与全局语义。

基本信息

常用类型INNER、LEFT、RIGHT、FULL、CROSS、ASOF(按最近时间匹配)
ANY 语义LEFT ANY JOIN 在右表有多条匹配时只取一行,避免结果行数膨胀
分布式行为GLOBAL JOIN 先把右表汇总再分发,普通 JOIN 在每个分片本地执行
执行方式右表常被加载进内存,内存不足时可能报错或落盘
版本注意早期版本 JOIN 能力有限,升级前先确认语法支持情况

典型使用场景

  • 宽表补维度:给事实表补上用户或商品名称
  • 按时间就近匹配:取事件发生前最近一次配置或价格
  • 事实表关联维表后再聚合,做多维度统计
  • 把 IN 子查询改写成 JOIN,换取更可控的执行计划
  • 本地表与外部引擎表关联,做跨系统数据拼接

常用写法

常用写法
-- 常规左连接:补上用户名称
SELECT e.ts, e.user_id, u.name
FROM events AS e
LEFT JOIN users AS u ON e.user_id = u.id
WHERE e.ts >= today();

-- 按时间就近匹配:取插入时刻前最近一次配置
SELECT e.ts, e.id, c.cfg_version
FROM events AS e
ASOF LEFT JOIN configs AS c
ON e.id = c.id AND e.ts >= c.ts;

-- 右表多条匹配时只取一行,避免结果行数膨胀
SELECT e.id, u.name
FROM events AS e
LEFT ANY JOIN users AS u ON e.user_id = u.id;

-- 分布式环境下需要全局语义时使用 GLOBAL JOIN
SELECT count()
FROM dist_events AS e
GLOBAL LEFT JOIN dist_users AS u ON e.user_id = u.id;

JOIN 变体与取舍

写法语义注意
INNER JOIN两边都存在才返回结果变少时要确认是否该用 LEFT
LEFT ANY JOIN右表多匹配只取一行避免膨胀,但取哪一行不确定
ASOF JOIN匹配最近一行满足条件的记录用于时间序列式的补值
GLOBAL JOIN右表先汇总再分发到各分片分布式查询的正确性保障,代价更高
多表 JOIN 时把行数少的表按顺序放在右侧;复杂查询可以先用子查询把两张大表各自缩小到必要范围,内存峰值会明显下降。
右表超过可用内存时会报错或落到磁盘,join_algorithm 与内存相关设置要按数据量调整;数据量远超内存时,更稳的做法是先把小表物化成字典或预聚合结果。

易错点

  • 跨分布式表的 JOIN 不自动保证全局语义,普通 JOIN 只在各分片本地执行,跨分片本应匹配的行会被漏掉,需要 GLOBAL JOIN 或先把数据收敛到单表
  • JOIN 右表超过内存会报错或落盘,join_algorithm 与内存设置要按数据量调整,关联前先估算右表体积
  • 使用 ANY JOIN 牺牲了确定性:右表多条匹配时取哪一行没有保证,业务要求精确取值时应先按业务键去重
  • 把大表放在右侧会让每台机器都加载一份全量右表,内存与网络压力剧增,小表放右边是必须遵守的惯例

数据来源与参考

  • ClickHouse Docs: JOIN clause
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌