select a.c_id from a
inner join b on a.c_id = b.c_id
inner join (
select c.c_id from c
union
select d.c_id from d
) t on a.c_id = t.c_id
关系可以看做是:
a 且 b 且 ( c 或 d )
1
BiChengfei 2022-05-23 10:24:55 +08:00
你这个 SQL ,问题应该出在在内存中创建了 c 和 d 的交集的临时表,导致无法命中索引,执行的全表查询。那么我的想法就是不在内存中创建临时表
可执行以下 SQL ,效果应该相同: ``` select a.c_id from a inner join b on a.c_id = b.c_id inner join c on c.c_id = a.c_id union select a.c_id from a inner join b on a.c_id = b.c_id inner join d on d.c_id = a.c_id ``` |
2
BiChengfei 2022-05-23 10:31:59 +08:00
https://img.gejiba.com/images/64758a40d86b4252f789058746a61f31.png
可以通过连接关系,理解上面的 SQL |
3
asmile1993 2022-05-23 10:33:18 +08:00
执行计划呢?
|
4
asmile1993 2022-05-23 10:39:20 +08:00
c 、d 表数据量不大的情况下用 1 楼的方法没有问题,但要执行两次,再 union 起来,感觉代价还是大了点。用 exists 去判断好了(在 1 对多的情况下也可以避免数据重复)
select a.c_id from a inner join b on a.c_id = b.c_id where exists ( select 1 from c where c.c_id = a._cid ) or exists ( select 1 from d where d.c_id = a._cid ) |
5
leonhao 2022-05-23 11:20:56 +08:00
只取 a.c_id 为啥要 join ,直接用 in 或者 exists ,join 可能产生重复数据
|
6
c6h6benzene 2022-05-23 11:29:35 +08:00 via iPhone
c 或 d 里面一定要有?我可能会 left join c 、left join d 然后其他地方写条件。
|
7
haah 2022-05-23 19:18:10 +08:00
你的优化是指数据量的优化吧?
|
8
mrjnamei OP 回复一下大佬们:
业务场景是动态拼接 SQL. 根据页面编辑器组装查询条件,我拼出的 SQL 就是类似上面发的 SQL. 数据库是千万 /亿级别的数据量(starrocks), 之前用过 子查询,效率非常低,数据过大的场景可能会阻塞 IO. 1 楼老哥提供的思路实质上是集合的展开运算,但是在拼装 SQL 上会有比较大的压力。 |