in和exists的区别与SQL执行效率分析

时间:2022-11-14 14:18:20
可总结为:当子查询表比主查询表大时,用Exists;当子查询表比主查询表小时,用in

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

  select * from sysobjects where exists (select 1 from syscolumns where id=syscolumns.id)


  select * from sysobjects where id in (select id from syscolumns )

  set statistics io off



 (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

  select * from syscolumns where exists (select 1 from sysobjects where id=syscolumns.id)


  select * from syscolumns where id in (select id from sysobjects )

  set statistics io off





  (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 的话
in和exists的区别与SQL执行效率分析select * from test a 

in和exists的区别与SQL执行效率分析   from test where sort = a.sort and sid > a.sid) 

in和exists的区别与SQL执行效率分析select * from test a 

in和exists的区别与SQL执行效率分析  where sid in (select max(sid) from test where sort = a.sort) 

的执行效率要高三倍以上。具体的执行时间忘记了。但是结果我记得很清楚。在此之前我一直推崇第二种写法,后来就改第一种了。





in和exists的sql执行效率分析,再简单举一个例子:

in和exists的区别与SQL执行效率分析declare @t table(id ,), v varchar())

in和exists的区别与SQL执行效率分析insert @t select'a'

in和exists的区别与SQL执行效率分析union all select'b'

in和exists的区别与SQL执行效率分析union all select'c'

in和exists的区别与SQL执行效率分析union all select'd'

in和exists的区别与SQL执行效率分析union all select'e'

in和exists的区别与SQL执行效率分析union all select'b'

in和exists的区别与SQL执行效率分析union all select'c'

in和exists的区别与SQL执行效率分析--a语句in的sql写法

in和exists的区别与SQL执行效率分析select * from @t )

in和exists的区别与SQL执行效率分析--b语句exists的sql写法

in和exists的区别与SQL执行效率分析select * from @t a  from @t where id!=a.id and v=a.v) 

两条语句功能都是找到表变量@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执行效率有较清晰的了解。  

in和exists的区别与SQL执行效率分析的更多相关文章

  1. in和exists的区别与SQL执行效率

    in和exists的区别与SQL执行效率最近很多论坛又开始讨论in和exists的区别与SQL执行效率的问题,本文特整理一些in和exists的区别与SQL执行效率分析 SQL中in可以分为三类: 1 ...

  2. SQl 执行效率总结

    SQL执行效率总结 1.关于SQL查询效率,100w数据,查询只要1秒,与您分享: 机器情况 p4: 2.4 内存: 1 G os: windows 2003 数据库: ms sql server 2 ...

  3. PHP中file_exists与is_file、is_dir的区别,以及执行效率的比较 转自#冰雪傲骨#

    PHP中file_exists与is_file.is_dir的区别,以及执行效率的比较   判断文件是否存在,有2个常用的PHP函数:is_file 和 file_exists, 判断文件夹是否存在, ...

  4. SQL执行效率总结

    1.关于SQL查询效率,100w数据,查询只要1秒,与您分享: 机器情况 p4: 2.4 内存: 1 G os: windows 2003 数据库: ms sql server 2000 目的: 查询 ...

  5. 提高SQL执行效率的16种方法

      项目中优化sql语句执行效率的方法:1)尽量选择较小的列2)将where中用的比较频繁的字段建立索引3)select子句中避免使用'*'4)避免在索引列上使用计算.not in 和<> ...

  6. 记一次,因表变量导致SQL执行效率变慢

    场景 最近工作中,发现某同步JOB在执行中经常抛出SQL执行超时的问题,查看日志发现每次SQL执行的时间都是线性增长的,循环执行50次以后执行时间甚至超过了5分钟 JOB执行流程分析  首先,对于JO ...

  7. oracle sql 执行计划分析

    转自http://itindex.net/detail/45962-oracle-sql-%E8%AE%A1%E5%88%92 一.首先创建表 SQL> show user USER is &q ...

  8. SQL执行效率和性能测试方法总结

    对于做管理系统和分析系统的程序员,复杂SQL语句是不可避免的,面对海量数据,有时候经过优化的某一条语句,可以提高执行效率和整体运行性能.如何选择SQL语句,本文提供了两种方法,分别对多条SQL进行量化 ...

  9. SQL执行效率2-执行计划

    以下语句可以进行SQL 语句执行时间分析,两个Go之间就是SQL查询语句 use Work--数据库名 go set statistics profile on set statistics io o ...

随机推荐

  1. 【解决】SQL Server作业中Excel Application不能访问文件

    在通过SQL Server作业来实现定时任务时,出现如下错误: FullyQualifiedErrorId : ComMethodTargetInvocation使用“1”个参数调用“Add”时发生异 ...

  2. Opencv读取各种格式图片,在TBitmap上面重绘

    //opencv读取图片 cv::Mat image; //const char *fileName = "HeadImage-UI/Photo-001.bmp"; const c ...

  3. RichtextBox去除闪烁光标

    http://files.cnblogs.com/xe2011/CustomRichTextBox_HideCaret.rar richTextBox能高亮选择,光标仍在,没有光标闪烁 把重RichT ...

  4. 内存管理tcmalloc

    tcmalloc https://code.google.com/p/gperftools/

  5. Spring源码情操陶冶-AbstractApplicationContext&num;initApplicationEventMulticaster

    承接前文Spring源码情操陶冶-AbstractApplicationContext#initMessageSource 约定web.xml配置的contextClass为默认值XmlWebAppl ...

  6. 利用大白菜制作多系统启动U盘(win&plus;ubuntu&plus;PE&plus;&period;&period;&period;)

    网上提供的方法很多都过时了,不适用,要不就是讲的不清楚 我结合http://www.xuebuyuan.com/848003.html大神的方案,加以研究,整理出了此篇文章 先看下最终成果: 好了,感 ...

  7. Shiro中的授权问题

    在初识Shiro一文中,我们对Shiro的基本使用已经做了简单的介绍,不懂的小伙伴们可以先阅读上文,今天我们就来看看Shiro中的授权问题. Shiro中的授权,大体上可以分为两大类,一类是隐式角色, ...

  8. MyBatis进阶(四)

    mapper.xml文件的编写 mapper.xml映射文件实现数据库和实体类之间的映射关系,定义操作数据库的sql语句. 主体部分 文件头部 <?xml version="1.0&q ...

  9. ajax基础知识

    一个简单的ajax例子: Uncaught SyntaxError: Unexpected token input看看是否是漏了:或者函数没有() //更新单个简历完整度 function updat ...

  10. Java 把一个文本文档的内容复制到另一个文本文档

    src.txt放在工程目录下,dest.txt可创建,也可不创建.一旦运行程序,如果dest.txt不存在,将自行创建这个文本文档,再将src.txt中的内容复制到dest.txt import ja ...