说明
clickhouse 的 多表 join 操作,是将 右表数据 放入到内存中,然后将左表中的数据,依次与 右表比对。
在大数据中,右表数据量大,放入到内存中,是不行的,效率很慢
用 in 代替 join
当多表联查时,查询的数据仅从其中一张表出时,可考虑用 IN 操作而不是 JOIN
如下方式:
select a.* from 表1 a
where a.列1 in (select 列a from 表2 )
反例:
select a.* from 表1 a left join 表2 b
on a. 列1=b. 列a
大小表join
多表 join 时要满足 小表在右 的原则,右表关联时被加载到内存中与左表进行比较,ClickHouse中无论是 Left join 、Right join 还是 Inner join 永远都是拿着右表中的每一条记录到左表中查找该记录是否存在,所以 右表必须是小表
例子:
select a.* from 大表 a left join 小表 b on a.列1 = b.列a;
不会谓词下推(新版本不存在此问题)
在join查询时不会主动发起谓词下推的操作,需要 每个子查询提前完成过滤操作
需要注意的是,是否执行谓词下推,对性能影响差别很大(新版本中已经不存在此问题,但是需要注意谓词的位置的不同依然有性能的差异)
having会自动优化为prewhere
Explain syntax
select a.sid,avg(a.age) as avg_age from t_student_mt a left join t_student_mt2 b on a. sid=b. sid
group by a.sid
having b.age < 25
优化后的语句:
SELECT
sid,
avg(age) AS avg_age
FROM t_student_mt AS a
ALL LEFT JOIN t_student_mt2 AS b ON sid = b.sid #全关联查询
PREWHERE b.age < 25 # 优化成 PREWHERE
GROUP BY sid
注意:需要手动 在 join 之前进行过滤
尽量在 join 之前进行过滤
过滤条件放在 右表 子查询中,如下:
select a.sid,avg(a.age) as avg_age from t_student_mt a left join
( select * from t_student_mt2 prewhere age < 25 ) b -- 右表加了过滤,是小表
on a. sid=b. sid
group by a.sid
参考:https://blog.csdn.net/qq_40378034/article/details/120473116