现在的位置: 首页 > 综合 > 正文

in子查询、exists子查询、连接,效率的探讨

2018年05月04日 ⁄ 综合 ⁄ 共 5356字 ⁄ 字号 评论关闭

 http://topic.csdn.net/t/20030729/17/2085863.html

in子查询、exists子查询、连接,效率的探讨

楼主caiyunxia(夏才云)2003-07-29 17:09:01 在 MS-SQL Server / 基础类 提问

一直以为IN子查询比exists子查询效率低,而连接(JOIN)最高,  
  今天在“高级程序员考试(指南)”看到,IN子查询的效率比连接查询效率高  

1 楼txlicenhe(马可)回复于 2003-07-29 17:13:06 得分 0

EXISTS应该是最高的,IN比JON效率高?学到一招,等下测试  
  Top

2 楼erigido(丰田村农民)回复于 2003-07-29 17:19:21 得分 10

不是吧,in比join高?呵呵~~~~,我也学到一招Top

3 楼CSFish(海里唯一的鱼)回复于 2003-07-29 17:27:40 得分 10

IN子查询的效率是比连接查询效率高  
  不过好像exists查询效率也不高Top

4 楼sdhdy(大江东去...)回复于 2003-07-29 17:32:42 得分 10

IN子查询的效率比连接查询效率高?不会吧!Top

5 楼caiyunxia(夏才云)回复于 2003-07-29 17:36:08 得分 0

测试了吗?  
  Top

6 楼Leftie(左手,为人民币服务)回复于 2003-07-29 17:36:57 得分 10

可能还要考虑到具体的语句与环境Top

7 楼caiyunxia(夏才云)回复于 2003-07-29 17:45:40 得分 0

以下是SQL的帮助   (高级查询优化概念)  
  Microsoft®   SQL   Server™   2000   使用内存中的排序和哈希联接技术执行排序、交集、联合、差分等操作。SQL   Server   利用这种类型的查询计划支持垂直表分区,有时称其为分列存储。  
   
  SQL   Server   使用三种类型的联接操作:    
  嵌套循环联接  
  合并联接  
  哈希联接    
  如果一个联接输入很小(比如不到   10   行),而另一个联接输入很大而且已在其联接列上创建索引,则索引嵌套循环是最快的联接操作,因为它们需要最少的   I/O   和最少的比较。有关嵌套循环的更多信息,请参见了解嵌套循环联接。    
   
  如果两个联接输入并不小但已在二者联接列上排序(例如,如果它们是通过扫描已排序的索引获得的),则合并联接是最快的联接操作。如果两个联接输入都很大,而且这两个输入的大小差不多,则预先排序的合并联接提供的性能与哈希联接相似。然而,如果两个输入的大小相差很大,则哈希联接操作通常快得多。有关更多信息,请参见了解合并联接。    
   
  哈希联接可以有效处理很大的、未排序的非索引输入。它们对复杂查询的中间结果很有用,因为:    
   
  中间结果未经索引(除非已经显式保存到磁盘上然后创建索引),而且生成时通常不为查询计划中的下一个操作进行适当的排序。  
   
   
  查询优化器只估计中间结果的大小。由于估计的值在复杂查询中可能有很大的误差,因此如果中间结果比预期的大得多,则处理中间结果的算法不仅必须有效而且必须适度弱化。    
  哈希联接使得对非规范化的使用减少。非规范化一般通过减少联接操作获得更好的性能,尽管这样做有冗余之险(如不一致的更新)。哈希联接则减少使用非规范化的需要。哈希联接使垂直分区(用单独的文件或索引代表单个表中的几组列)得以成为物理数据库设计的可行选项。有关更多信息,请参见了解哈希联接。    
   
  Top

8 楼CrazyFor(冬眠的鼹鼠)回复于 2003-07-29 17:45:55 得分 10

不能简单这样说的,要看IN,exists等的()里面的语句的Top

9 楼caiyunxia(夏才云)回复于 2003-07-29 17:47:52 得分 0

以下是SQL的帮助   (高级查询优化概念)  
  Microsoft®   SQL   Server™   2000   使用内存中的排序和哈希联接技术执行排序、交集、联合、差分等操作。SQL   Server   利用这种类型的查询计划支持垂直表分区,有时称其为分列存储。  
   
  SQL   Server   使用三种类型的联接操作:    
  嵌套循环联接  
  合并联接  
  哈希联接    
  如果一个联接输入很小(比如不到   10   行),而另一个联接输入很大而且已在其联接列上创建索引,则索引嵌套循环是最快的联接操作,因为它们需要最少的   I/O   和最少的比较。有关嵌套循环的更多信息,请参见了解嵌套循环联接。    
   
  如果两个联接输入并不小但已在二者联接列上排序(例如,如果它们是通过扫描已排序的索引获得的),则合并联接是最快的联接操作。如果两个联接输入都很大,而且这两个输入的大小差不多,则预先排序的合并联接提供的性能与哈希联接相似。然而,如果两个输入的大小相差很大,则哈希联接操作通常快得多。有关更多信息,请参见了解合并联接。    
   
  哈希联接可以有效处理很大的、未排序的非索引输入。它们对复杂查询的中间结果很有用,因为:    
   
  中间结果未经索引(除非已经显式保存到磁盘上然后创建索引),而且生成时通常不为查询计划中的下一个操作进行适当的排序。  
   
   
  查询优化器只估计中间结果的大小。由于估计的值在复杂查询中可能有很大的误差,因此如果中间结果比预期的大得多,则处理中间结果的算法不仅必须有效而且必须适度弱化。    
  哈希联接使得对非规范化的使用减少。非规范化一般通过减少联接操作获得更好的性能,尽管这样做有冗余之险(如不一致的更新)。哈希联接则减少使用非规范化的需要。哈希联接使垂直分区(用单独的文件或索引代表单个表中的几组列)得以成为物理数据库设计的可行选项。有关更多信息,请参见了解哈希联接。    
   
  Top

10 楼zclxyh(谁说我不在乎)回复于 2003-07-29 17:49:59 得分 0

果真?Top

11 楼yangvxin1(小杨)回复于 2003-07-29 18:39:51 得分 0

X学习,一般是exists最高吧,接下来是join最后才是in呀。没搞错?Top

12 楼pengdali()回复于 2003-07-29 19:40:48 得分 30

当然了,exists   in   join   这个顺序,学校里就讲过呀,不过这是理论,exists和in我实践过,join就没比过,应该说数据量约大差别越明显。记得有一次解一道题,最后while循环+字符函数居然比join快,出忽我的意料Top

13 楼zjcxc(邹建)回复于 2003-07-29 20:09:20 得分 30

exists   肯定是最高的,这点不容怀疑.  
   
  我今天也专门做过测试.  
  select   name   from   表  
  与  
  if   exists(select   *   from   表)   print   'aa'  
   
  前者差不多10秒,而后一闪就出来了.Top

14 楼zjcxc(邹建)回复于 2003-07-29 20:09:53 得分 0

in   join   这两者就真的很难说了.Top

15 楼woyaofengle(清流2号)回复于 2003-07-29 21:23:31 得分 10

in比join高?呵呵~~~~,我也学到一招  
  Top

16 楼caiyunxia(夏才云)回复于 2003-07-30 08:39:17 得分 0

从SQL的帮助看,不同情况,in子查询、exists子查询、连接,效率高低是不样的  
  应选用不同的连接方式  
  在SQL   SERVER的查询优化有详细的说明Top

17 楼8992026(8992026)回复于 2003-07-30 09:13:24 得分 30

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   语句的,一般编程习惯应该是用exists而不用in.  
   
  和连接的比较情况太多,说不完  
   
  Top

18 楼caiyunxia(夏才云)回复于 2003-07-30 09:24:02 得分 0

许多包含子查询的   Transact-SQL   语句都可以改为用联接表示。而其它一些问题只能由子查询提出。在   Transact-SQL   中,包括子查询的语句和不包括子查询但语义上等效的语句在性能方面通常没有区别。但是,在一些必须检查存在性的情况中,使用联接会产生更好的性能。否则,为确保消除重复值,必须为外部查询的每个结果都处理嵌套查询。所以在这些情况下,联接方式会产生更好的效果Top

19 楼hqc(慢跑的风)回复于 2003-07-30 12:18:46 得分 0

希望高手多流点肥出来撒,呵呵,让小的们长长见识撒!  
  ~~in比join   快,。。。嘎嘎Top

20 楼nboys()回复于 2003-07-30 12:22:50 得分 0

in   和   join   比较效率,我可不一定就肯定是哪个高了Top

21 楼nboys()回复于 2003-07-30 12:23:51 得分 0

学习学习..........  
   
  有高招我就接^_^Top

22 楼caiyunxia(夏才云)回复于 2003-07-30 16:12:26 得分 0

继续Top

23 楼caiyunxia(夏才云)回复于 2003-07-30 16:41:53 得分 0

还有吗?Top

24 楼pengdali()回复于 2003-07-30 19:07:31 得分 20

in   和   join   的可比性不大,join应该和子查询比Top

25 楼robble(笑一笑十年少)回复于 2003-07-30 19:12:41 得分 0

知识的海洋,看来我没走错门!  
   
  各位前辈,各位大哥们大姐们,我是新来的,希望各位能多多帮助我!!  
   
  小弟在此祝各位大哥们大姐们工作顺利,钱包鼓鼓,家里红旗不倒,外面绿棋飘飘啊!!!Top

26 楼lzsheep(lzsheep)回复于 2003-07-30 20:03:00 得分 0

我认为还是要看你是怎么用的.Top

27 楼w_rose(w_rose)回复于 2003-07-30 21:52:24 得分 0

if   exists(select   *   from   表)  
  ------------------------------------  
  上面这个不能代表exits的主要作用。  
   
   
  查询快慢,要看能利用到索引减小多少次磁盘I/O操作。  
   
  比如,当表b上有大批记录时,  
  select   *   from   a   where   exists   (select   *   from   b   where   field2=a.field1)  
  当在field2上建立索引时,查询时间可能从500000降到2000。  
   
  但是,同样是建立了索引,同样的语句,在表b上只有千把个记录时,有索引反而比没索引要慢一点。  
   
  总的来说,对于记录数可大可小的表,应该从记录数较大的方面考虑,建立索引,并且在各种查询中尽量利用索引。Top

28 楼w_rose(w_rose)回复于 2003-07-30 21:55:20 得分 0

对于简单的exists、in、join,SQL   Server会自动相互转换,通常不可能看出运行速度的差别。  
   
  应该在同样配置下运行上百遍然后取平均值,千万不要只运行1遍就妄下结论,那样各个人都会得到不同的测试结论了。Top

29 楼tj_dns(愉快的登山者)回复于 2003-07-31 09:52:47 得分 10

如A,B两个表,  
  当只显示一个表的数据如A,关系条件只一个如ID时,使用IN更快:  
  select   *   from   A   where   id   in   (select   id   from   B)  
   
  当只显示一个表的数据如A,关系条件不只一个如ID,col1时,使用IN就不方便了,可以使用EXISTS:  
  select   *   from   A   where   exists   (select   1   from   B   where   id   =   A.id   and   col1   =   A.col1)  
   
  当只显示两个表的数据时,使用IN,EXISTS都不合适,要使用连接:  
  select   *   from   A   left   join   B   on   id   =   A.id    
   
  所以使用何种方式,要根据要求来定。  
 

抱歉!评论已关闭.