in和exists的区别与SQL执行效率
| in和exists的区别与SQL执行效率 最近很多论坛又开始讨论in和exists的区别与SQL执行效率的问题, 本文特整理一些in和exists的区别与SQL执行效率分析 SQL中in可以分为三类: 1、形如select * from t1 where f1 in ('a','b'),应该和以下两种比较效率 select * from t1 where f1='a' or f1='b' 或者 select * from t1 where f1 ='a' union all select * from t1 f1='b' 你可能指的不是这一类,这里不做讨论。 2、形如select * from t1 where f1 in (select f1 from t2 where t2.fx='x'), 其中子查询的where里的条件不受外层查询的影响,这类查询一般情况下,自动优化会转成exist语句,也就是效率和exist一样。 3、形如select * from t1 where f1 in (select f1 from t2 where t2.fx=t1.fx), 其中子查询的where里的条件受外层查询的影响,这类查询的效率要看相关条件涉及的字段的索引情况和数据量多少,一般认为效率不如exists。 除了第一类in语句都是可以转化成exists 语句的SQL,一般编程习惯应该是用exists而不用in,而很少去考虑in和exists的执行效率. in和exists的SQL执行效率分析 A,B两个表, (1)当只显示一个表的数据如A,关系条件只一个如ID时,使用IN更快: select * from A where id in (select id from B) (2)当只显示一个表的数据如A,关系条件不只一个如ID,col1时,使用IN就不方便了,可以使用EXISTS: select * from A where exists (select 1 from B where id = A.id and col1 = A.col1) (3)当只显示两个表的数据时,使用IN,EXISTS都不合适,要使用连接: select * from A left join B on id = A.id 所以使用何种方式,要根据要求来定。 这是一般情况下做的测试: 这是偶的测试结果: set statistics io on (47 行受影响) 表'syscolpars'。扫描计数 1,逻辑读取 3 次,物理读取 0 次,预读 2 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。 表'sysschobjs'。扫描计数 1,逻辑读取 3 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。 (1 行受影响) (44 行受影响) 表'syscolpars'。扫描计数 47,逻辑读取 97 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。 表'sysschobjs'。扫描计数 1,逻辑读取 3 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。 (1 行受影响) set statistics io on (419 行受影响) 表'syscolpars'。扫描计数 1,逻辑读取 10 次,物理读取 0 次,预读 15 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。 表'sysschobjs'。扫描计数 1,逻辑读取 3 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。 (1 行受影响) (419 行受影响) 表'syscolpars'。扫描计数 1,逻辑读取 10 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。 表'sysschobjs'。扫描计数 1,逻辑读取 3 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。 (1 行受影响) 测试结果(总体来讲exists比in的效率高): 效率:条件因素的索引是非常关键的 把syscolumns 作为条件:syscolumns 数据大于sysobjects 用in 扫描计数 47,逻辑读取 97 次, 用exists 扫描计数 1,逻辑读取 3 次 把sysobjects作为条件:sysobjects的数据少于syscolumns exists比in多预读 15 次 对此我记得还做过如下测试: 表 test 结构 id int identity(1,1), --id主键自增 sort int, --类别,每一千条数据为一个类别 sid int --分类id 插入600w条数据 如果要查询每个类别的最大sid 的话 select * from test a 比 select * from test a 的执行效率要高三倍以上。具体的执行时间忘记了。但是结果我记得很清楚。在此之前我一直推崇第二种写法,后来就改第一种了。 in和exists的sql执行效率分析,再简单举一个例子: declare @t table(id int identity(1,1), v varchar(10)) 两条语句功能都是找到表变量@t中,v含有重复值的记录. 第一条sql语句使用in,但子查询中与外部没有连系. 第二条sql语句使用exists,但子查询中与外部有连系. 大家看SQL查询计划,很清楚了. selec v from @t group by v having count(*)> 1 这条Sql语句,它的执行不依赖于主查询主句(我也不知道怎么来描述in外面的和里面的,暂且这么叫吧,大家明白就行) 那么,SQL在查询时就会优化,即将它的结果集缓存起来 即缓存了 v --- b c 后续的操作,主查询在每处理一步时,相当于在处理 where v in('b','c') 当然,语句不会这么转化, 只是为了说明意思,也即主查询每处理一行(记为currentROW时,子查询不会再扫描表, 只会与缓存的结果进行匹配 而 select 1 from @t where id!=a.id and v=a.v 这一句,它的执行结果依赖于主查询中的每一行. 当处理主查询第一行时 即 currentROW(id=1)时, 子查询再次被执行 select 1 from @t where id!=1 and v='a' 扫描全表,从第一行记 currentSubROW(id=1) 开始扫描,id相同,过滤,子查询行下移,currentSubROW(id=2)继续,id不同,但v值不匹配,子查询行继续下移...直到currentSubROW(id=7)没找到匹配的, 子查询处理结束,第一行currentROW(id=1)被过滤,主查询记录行下移 处理第二行时,currentROW(id=2), 子查询 select 1 from @t where id!=2 and v='b' ,第一行currentSubROW(id=1)v值不匹配,子查询下移,第二行,id相同过滤,第三行,...到第六行,id不同,v值匹配, 找到匹配结果,即返回,不再往下处理记录. 主查询下移. 处理第三行时,以此类推... sql优化中,使用in和exist? 主要是看你的筛选条件是在主查询上还是在子查询上。 通过分析,相信大家已经对in和exists的区别、in和exists的SQL执行效率有较清晰的了解。 本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/qzww5324/archive/2009/04/23/4103115.aspx |
in和exists的区别与SQL执行效率的更多相关文章
- in和exists的区别与SQL执行效率分析
可总结为:当子查询表比主查询表大时,用Exists:当子查询表比主查询表小时,用in SQL中in可以分为三类: 1.形如select * from t1 where f1 in ('a','b'), ...
- SQl 执行效率总结
SQL执行效率总结 1.关于SQL查询效率,100w数据,查询只要1秒,与您分享: 机器情况 p4: 2.4 内存: 1 G os: windows 2003 数据库: ms sql server 2 ...
- PHP中file_exists与is_file、is_dir的区别,以及执行效率的比较 转自#冰雪傲骨#
PHP中file_exists与is_file.is_dir的区别,以及执行效率的比较 判断文件是否存在,有2个常用的PHP函数:is_file 和 file_exists, 判断文件夹是否存在, ...
- SQL执行效率总结
1.关于SQL查询效率,100w数据,查询只要1秒,与您分享: 机器情况 p4: 2.4 内存: 1 G os: windows 2003 数据库: ms sql server 2000 目的: 查询 ...
- 提高SQL执行效率的16种方法
项目中优化sql语句执行效率的方法:1)尽量选择较小的列2)将where中用的比较频繁的字段建立索引3)select子句中避免使用'*'4)避免在索引列上使用计算.not in 和<> ...
- 记一次,因表变量导致SQL执行效率变慢
场景 最近工作中,发现某同步JOB在执行中经常抛出SQL执行超时的问题,查看日志发现每次SQL执行的时间都是线性增长的,循环执行50次以后执行时间甚至超过了5分钟 JOB执行流程分析 首先,对于JO ...
- SQL执行效率和性能测试方法总结
对于做管理系统和分析系统的程序员,复杂SQL语句是不可避免的,面对海量数据,有时候经过优化的某一条语句,可以提高执行效率和整体运行性能.如何选择SQL语句,本文提供了两种方法,分别对多条SQL进行量化 ...
- SQL执行效率2-执行计划
以下语句可以进行SQL 语句执行时间分析,两个Go之间就是SQL查询语句 use Work--数据库名 go set statistics profile on set statistics io o ...
- [转]SQLServer SQL执行效率和性能测试方法总结
本文转自:http://www.zhixing123.cn/net/27495.html 对于做管理系统和分析系统的程序员,复杂SQL语句是不可避免的,面对海量数据,有时候经过优化的某一条语句,可以提 ...
随机推荐
- 深入研究Java类加载机制
类加载是Java程序运行的第一步,研究类的加载有助于了解JVM执行过程,并指导开发者采取更有效的措施配合程序执行. 研究类加载机制的第二个目的是让程序能动态的控制类加载,比如热部署等,提高程序的灵活性 ...
- JS计算字符串所占字节数
最近项目有个需求要用js计算一串字符串写入到localStorage里所占的内存,众所周知的,js是使用Unicode编码的.而Unicode的实现有N种,其中用的最多的就是UTF-8和UTF-16. ...
- 【HDOJ】4729 An Easy Problem for Elfness
其实是求树上的路径间的数据第K大的题目.果断主席树 + LCA.初始流量是这条路径上的最小值.若a<=b,显然直接为s->t建立pipe可以使流量最优:否则,对[0, 10**4]二分得到 ...
- Android开发之少去踩坑,多走捷径【转】
作者:gzjay,腾讯MIG无线产品部 高级工程师 最近一朋友提了几个Android问题让我帮忙写个小分享,我觉得对新人还是挺有帮助的,所以有了这个小分享. 1.目前, Android APP开发完成 ...
- one-to-many many-to-one配置解释
one-to-many放在某个文件的配置中,表示这个文件是ONE的一方, 同样的many-to-one放在某个文件的配置中,表示这个文件是many的一方.
- shell脚本编写笔记
包含转载内容,转载自http://wenku.baidu.com/link?url=jtCHxEYzgGve6P64U3JRQRgU6nhpGvqFLLpWu9I2Htq6hi9TGLudRFkk7r ...
- mycat分布式mysql中间件(数据库切分概述)[转]
mysql数据库切分 前言 通 过MySQLReplication功能所实现的扩展总是会受到数据库大小的限制,一旦数据库过于庞大,尤其是当写入过于频繁,很难由一台主机支撑的时 候,我们还是会面临到扩展 ...
- 31、activity 四种工作模式
一个应用通常(不一定)对应一个任务栈,相当于有个集合,保存了这个app里所有的页面栈的规则是先进后出,"进"就相当于打开了一个页面,"出"就相当于返回时关闭一个 ...
- MSP430单片机输入与输出
MSP430单片机的输入输出线绝大多数是服用的,除了个别的端口外,基本上是8为为一组,不同的型号的MSP430的端口有所不同,就msp430F5438而言,一共有11个I/O端口,其中除了第十一P11 ...
- 168. Excel Sheet Column Title
Excel Sheet Column Title Given a positive integer, return its corresponding column title as appear i ...