WHERE条件中or与union引起的全表扫描的问题
说起数据库的SQL语句执行效率的问题,就不得不提where条件语句中的or(逻辑或)引起的全表扫描问题,从而导致效率下降。
在以往绝大多数的资料中,大多数人的建议是使用 union 代替 or ,以解决由于使用了 OR 导致的全表扫描。然而,实际是不是如此呢?flymorn就拿5万多条数据的MSSQL数据库来测试。
在SQL Server查询分析器中键入如下代码:
SET STATISTICS io ON
SET STATISTICS time ON
go
select * from chuzu where c_id>1000 or c_qu='沙坪坝区' order by c_time desc
select * from chuzu where c_id>1000 
union
select * from chuzu where c_qu='沙坪坝区' order by c_time desc
go
SET STATISTICS profile OFF
SET STATISTICS io OFF
SET STATISTICS time OFF
数据库设计中,id为主键,同时也是聚集索引,qu是普通字段列,两个条件中的字段是不一样的。
执行计划如下:

从执行计划中可以看出,采用了 union 的SQL语句的查询成本为50.22%,比采用 or 的成本 49.78%稍多,当然这只是计划。我们再来看看执行效率:
表 'chuzu'。扫描计数 1,逻辑读 2412 次,物理读 0 次,预读 0 次。
SQL Server 执行时间: CPU 时间 = 938 毫秒,耗费时间 = 3222 毫秒。
(所影响的行数为 52713 行)
表 'chuzu'。扫描计数 2,逻辑读 4774 次,物理读 0 次,预读 0 次。
SQL Server 执行时间:  CPU 时间 = 1484 毫秒,耗费时间 = 4323 毫秒。
从这样的数据可以看出,采用了 union 的SQL语句的效率(4323 毫秒)实际上并没有比采用 or (3222 毫秒) 的高,耗费的时间也要多,采用了 or 的效率反而高出了25%。
如果where条件中的是同一个字段的话,执行效率也大体如上。
SET STATISTICS io ON
SET STATISTICS time ON
go
select * from chuzu where c_qu='九龙坡区' or c_qu='沙坪坝区' order by c_time desc
select * from chuzu where c_qu='九龙坡区'
union
select * from chuzu where c_qu='沙坪坝区' order by c_time desc
go
SET STATISTICS profile OFF
SET STATISTICS io OFF
SET STATISTICS time OFF
在这样的执行计划中,union 成本为 60.75% ,采用 or 的成本为 39.25%。依然是or的效率高。

再来看执行结果:
表 'chuzu'。扫描计数 1,逻辑读 2412 次,物理读 0 次,预读 0 次。
SQL Server 执行时间: CPU 时间 = 203 毫秒,耗费时间 = 635 毫秒。
(所影响的行数为 6131 行)
表 'chuzu'。扫描计数 2,逻辑读 4824 次,物理读 0 次,预读 0 次。
SQL Server 执行时间:  CPU 时间 = 360 毫秒,耗费时间 = 798 毫秒。
采用union的执行时间 798 ms ,or的时间是 635ms,效率上来说,依然是 or 的效率高。
总结:我的测试结果正和网上说的相反,也许是因为我的数据量还不够大,才5万多的数据;或许当数据量到了百万千万级的时候,union 的效率 就会比 or 的高了。
所以,我的理解是在数据量还没有足够大,sql语句中还是尽量用 or 条件查询,因为数据量不大的情况下,即使全表扫描也要比逻辑读两次,扫描两次的时间要少,效率要高;当然,如果你的数据达到百万级别以上了,那就不要用 or 了,可以用 union 或 union all 代替 or ,以避免因为 or 引起的全表扫描。
WHERE条件中or与union引起的全表扫描的问题的更多相关文章
- SQL中哪些情况会引起全表扫描
		
1.模糊查询效率很低:原因:like本身效率就比较低,应该尽量避免查询条件使用like:对于like '%...%'(全模糊)这样的条件,是无法使用索引的,全表扫描自然效率很低:另外,由于匹配算法的关 ...
 - SQL SERVER中关于OR会导致索引扫描或全表扫描的浅析
		
在SQL SERVER的查询语句中使用OR是否会导致不走索引查找(Index Seek)或索引失效(堆表走全表扫描 (Table Scan).聚集索引表走聚集索引扫描(Clustered Index ...
 - SQL SERVER中关于OR会导致索引扫描或全表扫描的浅析 (转载)
		
在SQL SERVER的查询语句中使用OR是否会导致不走索引查找(Index Seek)或索引失效(堆表走全表扫描 (Table Scan).聚集索引表走聚集索引扫描(Clustered Index ...
 - mysql in 中使用子查询,会不使用索引而走全表扫描
		
所以可以将 in 条件中 子查询转换成一张子表,从而通过 join 的形式进行条件限制.
 - MySQL中的全表扫描和索引树扫描
		
引言 在学习mysql时,我们经常会使用explain来查看sql查询的索引等优化手段的使用情况.在使用explain时,我们可以观察到,explain的输出有一个很关键的列,它就是type属性,ty ...
 - update的where条件要把索引的字段带上,要不然就全表锁
		
update的where条件要把索引的字段带上,要不然就全表锁 文章目录 update的where条件要把索引的字段带上,要不然就全表锁 本文主要内容 背景 ...
 - oracle where 后面的条件中|| 是什么意思
		
oracle where 后面的条件中|| 是连接符号,Oracle中另一个concat函数能够连接两个字符串 concat(a,b) Oracle中nvl函数的使用方法和作用是什么? 假设你某个字段 ...
 - Ext.Net 使用总结之查询条件中的起始日期
		
2.关于查询条件中起始日期的布局方式 首先上一张图,来展示一下我的查询条件的布局,如下: 大多数时候,我们的查询条件都是一个条件占一个格子,但也有不同的时候,如:查询条件是起始日期,则需要将这两个条件 ...
 - TSQL:A表字段与B表中的关联,关联条件中一列是随机关联的实现方式
		
A表字段与B表中的关联,关联条件中一列是随机关联的实现方式 create table test( rsrp string, rsrq string, tkey string, distan strin ...
 
随机推荐
- tensorflow ImportError: libmklml_intel.so: cannot open shared object file: No such file or directory
			
通过whl文件安装 tensorflow,显示缺少libmklml_intel.so 需要 1)安装intel MKL库 https://software.intel.com/en-us/articl ...
 - June 12th 2017 Week 24th Monday
			
All the splendor in the world is not worth a good friend. 人世间所有的荣华富贵都比不上有一个好朋友. It's great to have a ...
 - May 30th 2017 Week 22nd Tuesday
			
Knowledge will give you power, but character respect. 知识给你力量,品格给你别人的尊敬. Good characters can help us ...
 - python入门9 条件语句
			
条件语句: if 条件为真: 执行语句块 (执行完结束不执行elif,else) elif 条件为真: 执行语句块 (执行完结束不执行else) else: 执行语句块 #coding:utf-8 # ...
 - JQuery前端技术记录
			
[Jquery-leearning notes-2015]by lijun 1 Jquery是javascript实现的库,目标在于改变web应用的高交互性的方式. 其不唐突性:样式(.css). ...
 - POSIX多线程—线程基本概念
			
http://blog.csdn.net/livelylittlefish/article/details/7957007 作者:阿波链接:http://blog.csdn.net/livelylit ...
 - Android数字签名解析(一)
			
一.数字签名概述 所谓"数字签名"就是通过某种password运算生成一系列符号及代码组成电子password进行签名,来取代书写签名或印章. 数字签名有两种功效:一是能确定消息 ...
 - Visual Studio C++ Win32控制台应用程序,Win32项目,MFC的区别
			
背景 Visual Studio C++ 创建新项目蹦出来如下选项: Win32控制台应用程序,Win32项目,MFC有什么区别? 正文: Win32控制台,没有界面,命令行执行生成的文件则直接在后台 ...
 - js学习笔记-数字转罗马数字
			
function convert(num) { var ans = ""; var k = Math.floor(num / 1000); var h = ...
 - Android学习笔记_23_服务Service之AIDL和远程服务实现进程通信以及进程间传递自定义类型参数
			
一.了解AIDL语言: 在Android中, 每个应用程序都有自己的进程,当需要在不同的进程之间传递对象时,该如何实现呢? 显然, Java中是不支持跨进程内存共享的.因此要传递对象, 需要把对象解析 ...