http://topic.csdn.net/t/20030729/17/2085863.html
in子查询、exists子查询、连接,效率的探讨
一直以为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
所以使用何种方式,要根据要求来定。