(转)SQL中使用or影响性能的解决办法

原文地址:https://www.cnblogs.com/xuxiaona/p/4962727.htmlhtml

近期作了一个存储过程,执行时发现很是的慢,居然须要六、7秒!性能

经排查,发现时间主要都耗在了其中一段查询语句上。这个语句用于查出结构相同的两个表中,其中两个字段的任一个字段数据相同的记录。code

例如,A表的结构以下所示:htm

--会员表
CREATE Table Member
(      
MemberID int, --会员ID MemberName varchar(50), --会员姓名 MemberPhone varchar(50) --会员电话 ) go

B表的结构与A表彻底相同,假设表名为Member_Tmep。blog

如今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
  

 

这条语句看上去逻辑很清晰,写出来也很简洁,但执行起来为何却那么耗费时间呢?io

虽然我不清楚这条语句错在哪里,但也想到试着用另外一种方式来实现这个查询,因而我把这段查询语句改为了下面这样:class

--查询出会员姓名相同但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,能够改用bwteen...and语句。例如:

select * from Member where MemberID between 90 and 100

若是没法使用bwteen...and,那么仍然须要使用union方法了,如:

select * from Member where MemberName = '张三' 
union all
select * from Member where MemberName = '李四'

这里由于会员姓名为“张三”的和为“李四”的不可能有重复记录,所以可使用性能更高的union all,而不是union了。

相关文章
相关标签/搜索