请教大家一个 SQL 的问题

2021-09-07 09:54:07 +08:00
 mugglezzz

需求是这样的,就是有 A 、B 两个表,两个表都有 ID 、FullName 、ShortName 三个字段,以及各有一些其他的字段,现在想要这两个表连接查询,条件是 优先 ID 相等,其次 FullName 相等,最后 ShortName 相等的记录,目前是这么做的:

select A.*,B.* from A left join B 
on (A.ID=B.ID and B.ID is not null) 
or (A.FullName=B.FullName and B.FullName is not null)
or (A.ShortName=B.ShortName and B.ShortName is not null)

其中 A 表数据比较少,B 表数据有 20 多 w,这样查出来需要 30 几秒。。。个人觉得问题应该是出在这个 or 这里,但是不知道有什么办法,请问各位有什么优化的方法吗?

1031 次点击
所在节点    问与答
11 条回复
liprais
2021-09-07 09:59:24 +08:00
你要的不就是这三个条件的并集么
gam2046
2021-09-07 10:09:13 +08:00
首先确保三个字段都有索引,然后尝试 right join,即数据少的表 join 数据多的表,如果还是很慢,贴出来 explain 和机器配置
BiChengfei
2021-09-07 10:22:57 +08:00
信息太少,暂不知道怎么优化,
-- 第一种 sql 似乎可以简写下,不知道会不会命中索引
```
select A.*, B.* from A
inner join B on A.ID = B.ID or A.FullName = B.FullName or A.ShortName = B.ShortName
```

-- 第二种用 union 拼接,不知道这样去重可以吗,也不知道会不会命中索引
```
select distinct * from (
select
A.*,
B.*
from A
inner join B on A.ID = B.ID
union
select
A.*,
B.*
from A
inner join B on A.FullName = B.FullName
union
select
A.*,
B.*
from A
inner join B on A.ShortName = B.ShortName) temp
```
BiChengfei
2021-09-07 10:29:29 +08:00
左连接,左边表不能为 null,右边表可能为 null,你 sql 中把右边表为 null 的情况排除,那么就是内连接,所以改为 inner join
因为 mysql 会对你的 sql 进行解析优化,再加上有 is not null,所以以前的语句能不能命中索引不知道,不知道有人能有理有据的科普下吗
BiChengfei
2021-09-07 10:38:04 +08:00
union 如果可以,这个语句还可以优化,考虑到 id 、fullname 、shortname,这三种匹配数据量的问题,在子语句中进行排除重复数据
zhangyaxiao072
2021-09-07 10:44:17 +08:00
@BiChengfei 我也想到了第二种,不需要 distinct 了吧,union 会去重
BiChengfei
2021-09-07 10:46:10 +08:00
@zhangyaxiao072 不知道,很少用这个,楼主试一下就知道了,小问题
mugglezzz
2021-09-07 10:47:30 +08:00
@BiChengfei #5
@zhangyaxiao072 #6
谢谢,我试一下看看
Egfly
2021-09-07 11:25:49 +08:00
要不考虑一下分开查?然后代码里根据业务合并结果集。没必要给数据库太多压力
coderJie
2021-09-07 15:15:32 +08:00
一般来说都是用第二种 union 的方式来代替 or 的方式
@Egfly 用代码来实现 union 效果的话会增加内存开销,一般交给数据库来操作就可以了,只要数据库不要太拉闸...
coderJie
2021-09-07 15:16:41 +08:00
@Egfly 数据量小的可以这么做,数据量大的话还是交给数据库吧

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

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

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

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

© 2021 V2EX