论坛首页 综合技术论坛

in 和 exists的区别 用数据说话

浏览 41170 次
该帖已经被评为良好帖
作者 正文
   发表时间:2012-05-30  
楼主很认真,值得尊敬。
0 请登录后投票
   发表时间:2012-05-30  
liguocai2009 写道
引用

举个例子:
例如:表A(小表),表B(大表),CC列上有索引
在外表小,内表大的情况下用in(Hash Join A和B两个表).效率就会很低,比如:
select * from A where cc in (select cc from B)
这个时候查询用到了A表上cc列的索引,但是因为A是小表,而且大表B上的索引也没有充分利用,因此效率不高

而如果用了exist,我们发现走的是对A,B两个表的nested Loop,对于遍历A的每一行,都会对大表B进行一次查询(可能对B表的查询结果不是太多.)
select * from A where exists(select cc from B where cc=A.cc)
这样效率会高些,因为用到了B表(大表)上cc列的索引。

not in 和not exists
如果查询语句使用了not in 那么内外表都进行全表扫描,没有用到索引;
而not extsts 的子查询依然能用到表上的索引。
所以无论那个表大,用not exists都比not in要快。

内表外表我不明白是什么意思,楼主的贴我没看明白。我只是看明白另外一篇讨论(如上),这篇从索引角度分析了exists和in的效率,很好懂,然而对下面的我就看不懂了为什么了,有人能解释一下吗?(我连什么叫外表,驱动表,内表的定义,为什么这么叫都不知道。。。)


引用

简单的说 in 是先内表,后外表,exist是先外表,后内表。
几个判断依据:
1.是否存在排序,排序都是耗资源的
2.是否走索引


这里讲了in和exist的执行顺序是不一样的。有人能用java程序写下exists和in的实现代码吗?
为什么顺序不一样,导致效率是不一样的?
如果外表是m行,内表是n行,不管先外后内,还是先内后外,结果不也是要循环m*n次吗?




楼主能够抽点时间解答我的疑问吗?
0 请登录后投票
   发表时间:2012-05-30  
liguocai2009 写道
liguocai2009 写道
引用

举个例子:
例如:表A(小表),表B(大表),CC列上有索引
在外表小,内表大的情况下用in(Hash Join A和B两个表).效率就会很低,比如:
select * from A where cc in (select cc from B)
这个时候查询用到了A表上cc列的索引,但是因为A是小表,而且大表B上的索引也没有充分利用,因此效率不高

而如果用了exist,我们发现走的是对A,B两个表的nested Loop,对于遍历A的每一行,都会对大表B进行一次查询(可能对B表的查询结果不是太多.)
select * from A where exists(select cc from B where cc=A.cc)
这样效率会高些,因为用到了B表(大表)上cc列的索引。

not in 和not exists
如果查询语句使用了not in 那么内外表都进行全表扫描,没有用到索引;
而not extsts 的子查询依然能用到表上的索引。
所以无论那个表大,用not exists都比not in要快。

内表外表我不明白是什么意思,楼主的贴我没看明白。我只是看明白另外一篇讨论(如上),这篇从索引角度分析了exists和in的效率,很好懂,然而对下面的我就看不懂了为什么了,有人能解释一下吗?(我连什么叫外表,驱动表,内表的定义,为什么这么叫都不知道。。。)


引用

简单的说 in 是先内表,后外表,exist是先外表,后内表。
几个判断依据:
1.是否存在排序,排序都是耗资源的
2.是否走索引


这里讲了in和exist的执行顺序是不一样的。有人能用java程序写下exists和in的实现代码吗?
为什么顺序不一样,导致效率是不一样的?
如果外表是m行,内表是n行,不管先外后内,还是先内后外,结果不也是要循环m*n次吗?




楼主能够抽点时间解答我的疑问吗?


效率高低要看执行计划! 执行计划说了算!

你写的sql可能是A样子,但执行计划可能把它解释为B样子。
0 请登录后投票
   发表时间:2012-05-30  
引用

简单的说 in 是先内表,后外表,exist是先外表,后内表。
几个判断依据:
1.是否存在排序,排序都是耗资源的
2.是否走索引

SQL1: select * from A where cc in (select cc from B) ;
SQL2: select * from A where exists(select cc from B where cc=A.cc) ;

这里讲了in和exist的执行顺序是不一样的。有人能用java程序写下exists和in的实现代码吗?

我想问的问题是:
为什么顺序不一样,导致效率是不一样的?

如果外表是m行,内表是n行,不管先外后内,还是先内后外,结果不也是要循环m*n次吗? 为什么效率会不一样?

0 请登录后投票
   发表时间:2012-05-30   最后修改:2012-05-30
liguocai2009 写道
引用

简单的说 in 是先内表,后外表,exist是先外表,后内表。
几个判断依据:
1.是否存在排序,排序都是耗资源的
2.是否走索引

SQL1: select * from A where cc in (select cc from B) ;
SQL2: select * from A where exists(select cc from B where cc=A.cc) ;

这里讲了in和exist的执行顺序是不一样的。有人能用java程序写下exists和in的实现代码吗?

我想问的问题是:
为什么顺序不一样,导致效率是不一样的?

如果外表是m行,内表是n行,不管先外后内,还是先内后外,结果不也是要循环m*n次吗? 为什么效率会不一样?



通过执行计划 看 外表 和 内表  是否走索引

in 和 exists只是一个关键字


如果外表是m行,内表是n行,不管先外后内,还是先内后外,结果不也是要循环m*n次吗? 为什么效率会不一样?
因为如果n表有索引 那么可以通过索引来获取数据 复杂度可以是o(logn)
0 请登录后投票
   发表时间:2012-05-30  
5、 not in 不走索引的,因此不能用
6、 not exists走索引的。

这个和索引也有关?
0 请登录后投票
   发表时间:2012-05-31  
第二个用例你用了group By,你要不用group by呢?

select count(*) from base_customer_sign where signCustomerUuid in (select uuid
from base_customer where trueName like 'user%' <Strong>group by</Strong> uuid)
0 请登录后投票
   发表时间:2012-05-31  
你的优化模式是choose,这种模式可以在RBO和CBO之间选择,你的执行计划中,没有成本的数据,执行中应该是选择RBO了,10g之后都是使用CBO,RBO已经被淘汰了,你的测试结果没有意义,建议使用CBO测试吧。
0 请登录后投票
   发表时间:2012-05-31  
hudingchen 写道
你的优化模式是choose,这种模式可以在RBO和CBO之间选择,你的执行计划中,没有成本的数据,执行中应该是选择RBO了,10g之后都是使用CBO,RBO已经被淘汰了,你的测试结果没有意义,建议使用CBO测试吧。

因为我用的是oracle9i 所以直接使用oracle9i测试了! 有时间用CBO测试下!
0 请登录后投票
   发表时间:2012-06-01  
liguocai2009 写道
引用

举个例子:
例如:表A(小表),表B(大表),CC列上有索引
在外表小,内表大的情况下用in(Hash Join A和B两个表).效率就会很低,比如:
select * from A where cc in (select cc from B)
这个时候查询用到了A表上cc列的索引,但是因为A是小表,而且大表B上的索引也没有充分利用,因此效率不高

而如果用了exist,我们发现走的是对A,B两个表的nested Loop,对于遍历A的每一行,都会对大表B进行一次查询(可能对B表的查询结果不是太多.)
select * from A where exists(select cc from B where cc=A.cc)
这样效率会高些,因为用到了B表(大表)上cc列的索引。

not in 和not exists
如果查询语句使用了not in 那么内外表都进行全表扫描,没有用到索引;
而not extsts 的子查询依然能用到表上的索引。
所以无论那个表大,用not exists都比not in要快。

内表外表我不明白是什么意思,楼主的贴我没看明白。我只是看明白另外一篇讨论(如上),这篇从索引角度分析了exists和in的效率,很好懂,然而对下面的我就看不懂了为什么了,有人能解释一下吗?(我连什么叫外表,驱动表,内表的定义,为什么这么叫都不知道。。。)


引用

简单的说 in 是先内表,后外表,exist是先外表,后内表。
几个判断依据:
1.是否存在排序,排序都是耗资源的
2.是否走索引


这里讲了in和exist的执行顺序是不一样的。有人能用java程序写下exists和in的实现代码吗?
为什么顺序不一样,导致效率是不一样的?
如果外表是m行,内表是n行,不管先外后内,还是先内后外,结果不也是要循环m*n次吗?



顺序不一样?
in和exist 不都是先执行 子查询里,然后在判断是否有数据,在执行外面的查询。

m*n我觉得也是,除非有索引吧,不过oracle好像默认B树索引,所以应该不是m*n的全表查询,应该看代码情况

0 请登录后投票
论坛首页 综合技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics