静思苑 2016-03-27
在OracleSQL中取数据时有时要用到in和exists那么他们有什么区别呢?
1性能上的比较
比如Select*fromT1wherexin(selectyfromT2)
执行的过程相当于:
select*
fromt1,(selectdistinctyfromt2)t2
wheret1.x=t2.y;
相对的
select*fromt1whereexists(selectnullfromt2wherey=x)
执行的过程相当于:
forxin(select*fromt1)
loop
if(exists(selectnullfromt2wherey=x.x)
then
OUTPUTTHERECORD
endif
endloop
表T1不可避免的要被完全扫描一遍
分别适用在什么情况?
以子查询(selectyfromT2)为考虑方向
如果子查询的结果集很大需要消耗很多时间,但是T1比较小执行(selectnullfromt2wherey=x.x)非常快,那么exists就比较适合用在这里
相对应得子查询的结果集比较小的时候就应该使用in.
转载自http://hi.baidu.com/hopedaily/blog/item/56d23edbde87cd60d0164efe.html
in和exists
in是把外表和内表作hash连接,而exists是对外表作loop循环,每次loop循环再对内表进行查询。
一直以来认为exists比in效率高的说法是不准确的。
如果查询的两个表大小相当,那么用in和exists差别不大。
如果两个表中一个较小,一个是大表,则子查询表大的用exists,子查询表小的用in:
例如:表A(小表),表B(大表)
1:
select*fromAwhereccin(selectccfromB)
效率低,用到了A表上cc列的索引;
select*fromAwhereexists(selectccfromBwherecc=A.cc)
效率高,用到了B表上cc列的索引。
相反的
2:
select*fromBwhereccin(selectccfromA)
效率高,用到了B表上cc列的索引;
select*fromBwhereexists(selectccfromAwherecc=B.cc)
效率低,用到了A表上cc列的索引。
in与=的区别
selectnamefromstudentwherenamein('zhang','wang','li','zhao');
与
selectnamefromstudentwherename='zhang'orname='li'orname='wang'orname='zhao'
的结果是相同的。
in内表全扫,exists外表全扫
in用到外表索引(外表大就快)exists用到子查询索引(子大就快)
notin和notexists
如果查询语句使用了notin那么内外表都进行全表扫描,没有用到索引;
而notextsts的子查询依然能用到表上的索引。
所以无论那个表大,用notexists都比notin要快。