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

近期做了一个存储过程,执行时发现非常的慢,竟然需要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,可以改用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了。

(转)SQL中使用or影响性能的解决办法的更多相关文章

  1. SQL中使用or影响性能的解决办法

    近期做了一个存储过程,执行时发现非常的慢,竟然需要6.7秒! 经排查,发现时间主要都耗在了其中一段查询语句上.这个语句用于查出结构相同的两个表中,其中两个字段的任一个字段数据相同的记录. 例如,A表的 ...

  2. Sql Server 2008 卸载重新安装失败的解决办法!(多次偿试,方法均有效!)

    Sql Server 2008 卸载重新安装失败的解决办法!(多次偿试,方法均有效!) 1.控制面板中卸载所有带sql server的程序. 2.在C盘C:\Program Files中sqlserv ...

  3. [org.hibernate.engine.jdbc.spi.SqlExceptionHelper]SQL Error: 1064, SQLState: 42000问题的解决办法

    [org.hibernate.engine.jdbc.spi.SqlExceptionHelper]SQL Error: 1064, SQLState: 42000问题的解决办法. 出现这种情况的原因 ...

  4. IIS关于“ 配置错误 不能在此路径中使用此配置节”的解决办法

    IIS关于“ 配置错误 不能在此路径中使用此配置节”的解决办法 原文链接:http://www.cnblogs.com/200325074/p/3679316.html 今天刚安装好IIS8.5, 我 ...

  5. Excel在任务栏中只显示一个窗口的解决办法

     Excel在任务栏中只显示一个窗口的解决办法  以前朋友遇到过这个问题,这次自己又遇到了,习惯了以前的那种在任务栏中显示全部窗口,方便用Alt+Tab键进行切换. 如果同时打开许多Excel工作簿, ...

  6. 在ASP.net中的UpdatePanel,弹窗失败解决办法

    原文:在ASP.net中的UpdatePanel,弹窗失败解决办法 最开始我用: Response.Write("<script>alert('和哈呵呵呵呵呵呵!')</s ...

  7. 在Windows2008下安装SQL Server 2005无法启动服务的解决办法

    在Windows2012下安装SQL Server 2005无法启动服务的解决办法 1.正常安装任一版本的SQL Server 2005. 2.安装到SqlServer服务的时候提示启动服务失败  此 ...

  8. Ubuntu中Android SDK Manager无法更新解决办法

    Ubuntu中Android SDK Manager无法更新解决办法http://hi.baidu.com/petercao2008/item/d7a64441f04668e81e19bc1a

  9. MySQL 执行SQL脚本 报ERROR 1231 (42000)的解决办法【转】

    今天在source mysqldump 备份文件时,发现导入的过程中报如下的错误: ERROR 1231 (42000): Variable 'time_zone' can't be set to t ...

随机推荐

  1. 痛苦的版本对齐(3) cygwin下的路径引用(sed解决篇)

    上次问题(见http://www.cnblogs.com/yvivid/p/3546649.html),.depend信息路径错误的问题. 主要尝试了,在(虚拟机下构建)linux下编译,确实没有问题 ...

  2. 计蒜客 Overlapping Rectangles (离散化)

    题意: 给定一个坐标系, 给出n个矩形的左下角坐标(bx,by)和右上角坐标(tx,ty) , 求矩形覆盖的面积, 有些区域会被多个矩形覆盖, 但只用算一次. n <= 1000,  0 < ...

  3. 如何在小程序实现图片lazy-load懒加载效果

    自从跳一跳出现之后小程序又开始频繁出现了,在学习过程中发现小程序虽然好但是由于api不完善导致开发过程中有很多的坑,重点是网上相对小程序出现坑时解决方案显然比较少,小程序最让人觉得痛心疾首之一就是无法 ...

  4. Python+selenium鼠标、键盘事件

    鼠标操作 现在的Web产品提供了丰富的鼠标交互方式,例如鼠标右击.双击.悬停.甚至是鼠标拖动等功能,在Webdriver中,将这些关于鼠标操作的方法封装在ActionChains类提供. 1.鼠标右击 ...

  5. 理工个人积分赛最后一场(FZU)G - 五子棋,坑爹的大水题~~

    Problem 1490 五子棋 Time Limit: 1000 mSec Memory Limit : 32768 KB  Problem Description 五子棋是起源于中国古代的传统黑白 ...

  6. POJ1450:Gridland 【杂题】

    题目大意:先给出了TSP的背景,然后给出一个n*m的单位格点的图,图中除边缘上的点与八个方向的点有边连接,距离为欧拉距离,求从左上角出发的TSP 思路:从水题列表中看到的题,但看一开始给出的backg ...

  7. 【贪心】codeforces A. Heidi and Library (easy)

    http://codeforces.com/contest/802/problem/A [题意] 有一个图书馆,刚开始没有书,最多可容纳k本书:有n天,每天会有人借一本书,当天归还:如果图书馆有这个本 ...

  8. hdu 3371

    #include<stdio.h> #include<stdlib.h> #define N 501 struct node { int x,y,dis; }road[N*N] ...

  9. poj3468区间延迟更新模板题

    #include<stdio.h> #include<string.h> #define N 100000 struct st{  int x,y;  __int64 yanc ...

  10. msp430入门编程17

    msp430中C语言的寄存器操作 msp430入门学习 msp430入门编程