(转)SQL中使⽤or影响性能的解决办法
近期做了⼀个存储过程,执⾏时发现⾮常的慢,竟然需要6、7秒!
经排查,发现时间主要都耗在了其中⼀段查询语句上。这个语句⽤于查出结构相同的两个表中,其中两个字段的任⼀个字段数据相同的记录。
例如,A表的结构如下所⽰:
--会员表
CREATE Table Member
(
MemberID int, --会员ID
MemberName varchar(50), --会员姓名
MemberPhone varchar(50) --会员电话
)
go
B表的结构与A表完全相同,假设表名为Member_Tmep。
现在Member表中有7000条不重复的数据,Member_Tmep表中有2000条数据,需要查出这两张表中,会员姓名或会员电话相同,但会员ID 不相同的记录。
按照普通的逻辑,我⼀开始是这样写的:
select a.MemberID,a.MemberName,a.MemberPhone
from Member a,Member_Tmep b
where (a.MemberName = b.MemberName or a.MemberPhone = b.MemberPhone) and a.MemberID <> b.MemberID
这条语句看上去逻辑很清晰,写出来也很简洁,但执⾏起来为什么却那么耗费时间呢?
虽然我不清楚这条语句错在哪⾥,但也想到试着⽤另⼀种⽅式来实现这个查询,于是我把这段查询语句改成了下⾯这样:
-
-查询出会员姓名相同但ID不同的记录
select a.MemberID,a.MemberName,a.MemberPhone
from Member a
inner join Member_Tmep b on a.MemberName = b.MemberName and a.MemberID <> b.MemberID
union
--再查询出会员电话相同但ID不同的记录,进⾏合并
select a.MemberID,a.MemberName,a.MemberPhone
from Member a
inner join Member_Tmep b on a.MemberPhone = b.MemberPhone and a.MemberID <> b.MemberID
这样再执⾏,秒秒钟就执⾏完了。
其实之前也写过很多类似第⼀种写法的SQL语句,⼀直没出过这种问题,那是因为数据量没有这么⼤。
应尽量避免在 where ⼦句中使⽤ or 来连接条件,否则将导致引擎放弃使⽤索引⽽进⾏全表扫描。⽽改⽤union之后,性能就⼤⼤提⾼了。
使⽤"union all"的性能⽐"union"更⾼⼀些。因为当SQL 语句需要UNION两个查询结果集合时,这两个结果集合会以UNION-ALL的⽅式被合并,然后在输出最终结果前进⾏排序。如果⽤UNION ALL替代UNION,这样排序就不是必要了,效率就会因此得到提⾼。
⽽在上⾯这个例⼦⾥使⽤"union"⽽不是"union all",是因为“会员姓名相同但ID不同的记录”和“会员电话相同但ID不同的记录”可能有重复,使⽤"union"可以去掉重复的记录。
其实这个道理之前也有看到过,但是在编写语句的时候经常习惯性的就⽤了简洁的or语句,慢慢也就忘了这回事了。。。
除了上述这种情况,还有⼀种常见的会使⽤or语句的情景,那就是:查询出某字段的值等于某⼏个特定值的记录。例如,需要查询出会员姓名为“张三”、“李四”的记录。我们可能会这样写:
select * from Member where MemberName = '张三' or MemberName = '李四'
通常情况下,这种写法是看不出有什么问题的,但是在数据量很⼤的情况下,⼀样会⾮常影响执⾏速度。
还有⼀种写法是使⽤in语句,例如下⾯这样:
select * from Member where MemberName in ('张三','李四')
但是有些说法认为in语句⼀样会导致全表扫描。in和not in的写法都是应该尽量避免的。
如果需要查询的特定值是连续的数值范围,如90--100,可以改⽤and语句。例如:
select * from Member where MemberID between 90 and 100
sql中union多表合并如果⽆法使⽤and,那么仍然需要使⽤union⽅法了,如:
select * from Member where MemberName = '张三'
union all
select * from Member where MemberName = '李四'
这⾥因为会员姓名为“张三”的和为“李四”的不可能有重复记录,因此可以使⽤性能更⾼的union all,⽽不是union了。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论