clickhouse21.7.11.3 SQL语法优化-多表关联查询

说明

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


原文出处:/show_1IX3RCLRIHQG.html