这个 SQL 有优化空间吗

2022-05-23 09:57:12 +08:00
 mrjnamei

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 )

2396 次点击
所在节点    MySQL
8 条回复
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
```
BiChengfei
2022-05-23 10:31:59 +08:00
https://img.gejiba.com/images/64758a40d86b4252f789058746a61f31.png
可以通过连接关系,理解上面的 SQL
asmile1993
2022-05-23 10:33:18 +08:00
执行计划呢?
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
)
leonhao
2022-05-23 11:20:56 +08:00
只取 a.c_id 为啥要 join ,直接用 in 或者 exists ,join 可能产生重复数据
c6h6benzene
2022-05-23 11:29:35 +08:00
c 或 d 里面一定要有?我可能会 left join c 、left join d 然后其他地方写条件。
haah
2022-05-23 19:18:10 +08:00
你的优化是指数据量的优化吧?
mrjnamei
2022-05-26 17:25:57 +08:00
回复一下大佬们:
业务场景是动态拼接 SQL. 根据页面编辑器组装查询条件,我拼出的 SQL 就是类似上面发的 SQL. 数据库是千万 /亿级别的数据量(starrocks), 之前用过 子查询,效率非常低,数据过大的场景可能会阻塞 IO. 1 楼老哥提供的思路实质上是集合的展开运算,但是在拼装 SQL 上会有比较大的压力。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/854627

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX