oracle exists和in的区别

作者&投稿:季王 (若有异议请与网页底部的电邮联系)
oracle 中 in 和exists用法区别~

是这样的
in 是返回的结果集

比如你只运行这一句
select sno from sc where cno='c002'
返回的是一列sno

但是exists则不同,返回的是布尔值

虽然里边那个没法单独运行
select * from sc a where cno='c001' and exists(select sno from sc b where cno='c002' and a.sno=b.sno) ;
后边必须要写上两者的关联

存在测试IN、NOT IN、EXISTS、NOT EXISTS
例:SELECT * FROM SC WHERE SNO IN
(SELECT SNO FROM STUDENT WHERE SSEX=’女’);
同:SELECT * FROM SC WHERE EXISTS
(SELECT * FROM STUDENT WHERE SSEX=’女’ AND SC.SNO=SNO);
返回所有女生的成绩

例:SELECT * FROM SC WHERE SNO NOT IN
(SELECT SNO FROM STUDENT WHERE SSEX=’女’);
同:SELECT * FROM SC WHERE NOT EXISTS
(SELECT * FROM STUDENT WHERE SSEX=’女’ AND SC.SNO=SNO);
返回性别不为女的记录

说明:使用EXISTS相比IN,当使用IN检索到数据非常少时,IN比EXISTS快,反之,使用EXISTS比IN快。
如果EXISTS后面的SELECT * 改为SELECT ‘常量’(例如,a, b, c等),速度会更快。
谓词中含有“全部、至少、没有”时,使用NOT EXISTS.

oracle中in,not in和exists,not exists之间的区别 一直听到的都是说尽量用exists不要用in,因为exists只判断存在而in需要对比值,所以exists比较快,但看了看网上的一些东西才发现根本不是这么回事。
下面这段是抄的
Select * from T1 where x in ( select y from T2 )
执行的过程相当于:
select *
from t1, ( select distinct y from t2 ) t2
where t1.x = t2.y;

select * from t1 where exists ( select null from t2 where y = x )
执行的过程相当于:
for x in ( select * from t1 )
loop
if ( exists ( select null from t2 where y = x.x )
then
OUTPUT THE RECORD
end if
end loop

从我的角度来说,in的方式比较直观,exists则有些绕,而且in可以用于各种子查询,而exists好像只用于关联子查询(其他子查询当然也可以用,可惜没意义)。
由于exists是用loop的方式,所以,循环的次数对于exists影响最大,所以,外表要记录数少,内表就无所谓了,而in用的是hash join,所以内表如果小,整个查询的范围都会很小,如果内表很大,外表如果也很大就很慢了,这时候exists才真正的会快过in的方式。
下面这段还是抄的
not in 和not exists
如果查询语句使用了not in 那么内外表都进行全表扫描,没有用到索引;
而not extsts 的子查询依然能用到表上的索引。
所以无论那个表大,用not exists都比not in要快。
也就是说,in和exists需要具体情况具体分析,not in和not exists就不用分析了,尽量用not exists就好了。


典型的连接类型共有3种:
排序 - - 合并连接(Sort Merge Join (SMJ) )
嵌套循环(Nested Loops (NL) )
哈希连接(Hash Join)

嵌套循环和哈希连接的算法还是有不同,在理论上哈希连接要快过排序和nl,当然实际情况比理论上有复杂的多,不过两者还是有差异的

1、关于在 Oracle8i 时代中in和exists的区别

这里有条SQL语句:select * from A where id in(select id from B)
以上查询使用了in语句,in()只执行一次,它查出B表中的所有id字段并缓存起来.之后,检查A表的id是否与B表中的id相等,如果相等则将A表的记录加入结果集中,直到遍历完A表的所有记录;
它的查询过程类似于以下过程
List resultSet=[];
Array A=(select * from A);
Array B=(select id from B);
for(int i=0;i<A.length;i++) {
for(int j=0;j<B.length;j++) {
if(A[i].id==B[j].id) {
resultSet.add(A[i]);
break;
}
}
}
return resultSet;
可以看出,当B表数据较大时不适合使用in(),因为它会B表数据全部遍历一次.
如:A表有10000条记录,B表有1000000条记录,那么最多有可能遍历10000*1000000次,效率很差.
再如:A表有10000条记录,B表有100条记录,那么最多有可能遍历10000*100次,遍历次数大大减少,效率大大提升.
结论1:in()适合B表比A表数据小的情况

这里还有一条SQL语句: select a.* from A a where exists(select 1 from B b where a.id=b.id)
以上查询使用了exists语句,exists()会执行A.length次,它并不缓存exists()结果集,因为exists()结果集的内容并不重要,重要的是结果集中是否有记录,如果有则返回true,没有则返回false.
它的查询过程类似于以下过程

List resultSet=[];
Array A=(select * from A)

for(int i=0;i<A.length;i++) {
if(exists(A[i].id) { //执行select 1 from B b where b.id=a.id是否有记录返回
resultSet.add(A[i]);
}
}
return resultSet;
结论2:exists()适合B表比A表数据大的情况
当B表比A表数据大时适合使用exists(),因为它没有那么遍历操作,只需要再执行一次查询就行.
如:A表有10000条记录,B表有1000000条记录,那么exists()会执行10000次去判断A表中的id是否与B表中的id相等.
如:A表有10000条记录,B表有100000000条记录,那么exists()还是执行10000次,因为它只执行A.length次,可见B表数据越多,越适合exists()发挥效果.
再如:A表有10000条记录,B表有100条记录,那么exists()还是执行10000次,还不如使用in()遍历10000*100次,因为in()是在内存里遍历比较,而exists()需要查询数据库,我们都知道查询数据库所消耗的性能更高,而内存比较很快.

当A表数据与B表数据一样大时,in与exists效率差不多,可任选一个使用.
In适合内外表都很大的情况,exists适合外表结果集很小的情况。

In和exists对比:
若子查询结果集比较小,优先使用in,若外层查询比子查询小,优先使
用exists。因为若用in,则Oracle会优先查询子查询,然后匹配外层查询,
若使用exists,则oracle会优先查询外层表,然后再与内层表匹配。最优化
匹配原则,拿最小记录匹配大记录

2、关于在 Oracle8i 之后 时代中in和exists的区别
in 是把外表和内表作hash join,而exists是对外表作loop,每次loop再对内表进行查询。

一直以来认为exists比in效率高的说法是不准确的。
如果查询的两个表大小相当,那么用in和exists差别不大。
如果两个表中一个较小,一个是大表,则子查询表大的用exists,子查询表小的用in:

例如:表A(小表),表B(大表)
1:
select * from A where cc in (select cc from B)
效率低,用到了A表上cc列的索引;
select * from A where exists(select cc from B where cc=A.cc)
效率高,用到了B表上cc列的索引。
相反的
2:
select * from B where cc in (select cc from A)
效率高,用到了B表上cc列的索引;
select * from B where exists(select cc from A where cc=B.cc)
效率低,用到了A表上cc列的索引。

带in的关联子查询是多余的,因为in子句和子查询中相关的操作的功能是一样的。如:
select staff_name from staff_member where staff_id in
(select staff_id from staff_func where staff_member.staff_id=staff_func.staff_id);

为非关联子查询指定exists子句是不适当的,因为这样会产生笛卡乘积。如:
select staff_name from staff_member where staff_id
exists (select staff_id from staff_func);
not in 和not exists
如果查询语句使用了not in 那么内外表都进行全表扫描,没有用到索引;
而not extsts 的子查询依然能用到表上的索引。
所以无论哪个表大,用not exists都比not in要快。
尽量不要使用not in子句。使用minus 子句都比not in 子句快,虽然使用minus子句要进行两次查询:
select staff_name from staff_member where staff_id in (select staff_id from staff_member minus select staff_id from staff_func where func_id like '81%');
in 与 "=" 的区别
select name from student where name in ('zhang','wang','li','zhao');

select name from student where name='zhang' or name='li' or name='wang' or name='zhao'
的结果是相同的。

3、关于在 Oracle8i 之后 时代中in和exists的区别

在ORACLE 11G大行其道的今天,还有很多人受早期版本的影响,记住一些既定的规则,
1.子查询结果集小,用IN
2.外表小,子查询表大,用EXISTS
这是完全错误的观点。在8i时代,这经常是正确的,但是现在已经11G了,马上12C就要面世了。其实在ORACLE 9i CBO就已经优化了IN,EXISTS的区别,ORACLE优化器有个查询转换器,很多SQL虽然写法不同,但是ORACLE优化器会根据既定规则进行查询重写,重写为优化器觉得效率最高的SQL,所以可能SQL写法不同,但是执行计划却是完全一样的。
IN与EXISTS有一点要记住:IN一般是用于非相关子查询,而EXISTS一般用于相关子查询。当然IN也可以用于相关子查询,EXISTS也可以用于非相关子查询。但是这区别很重要,虽然优化器很强大,但是查询转换是有一定的限制的,在EXISTS性能低下,无法进行相关查询转换,比如不能UNNEST SUBQUERY,那么可能我们需要改写SQL,通常可以用IN/JOIN等改写相关子查询,或对于含有OR的SEMI JOIN改为UNION ALL/UNION的形式。
下面就用例子说明一下:

DROP TABLE a;
DROP TABLE b;
CREATE TABLE a AS SELECT * FROM hr.employees;
CREATE TABLE b AS SELECT * FROM hr.employees;
--反复插入,构造20万行+
INSERT INTO a SELECT * FROM a;
INSERT INTO b SELECT * FROM a;
COMMIT;
BEGIN
dbms_stats.gather_table_stats(ownname => USER,tabname => 'a',estimate_percent => 100,cascade => TRUE);
dbms_stats.gather_table_stats(ownname => USER,tabname => 'b',estimate_percent => 100,cascade => TRUE);
END;
/

1.测试IN,EXISTS在简单查询中,是等价的
SQL> set autotrace traceonly exp
SQL> SELECT * FROM a
2 WHERE EXISTS(
3 SELECT 1 FROM b WHERE a.employee_id=b.employee_id);

执行计划
----------------------------------------------------------
Plan hash value: 2317816356

---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 217K| 15M| 1375 (2)| 00:00:17 |
|* 1 | HASH JOIN | | 217K| 15M| 1375 (2)| 00:00:17 |
| 2 | SORT UNIQUE | | 217K| 848K| 126 (1)| 00:00:02 |
| 3 | INDEX FAST FULL SCAN | IDX2_B | 217K| 848K| 126 (1)| 00:00:02 |
| 4 | TABLE ACCESS FULL | A | 217K| 14M| 620 (1)| 00:00:08 |
---------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - access("A"."EMPLOYEE_ID"="B"."EMPLOYEE_ID")

SQL> SELECT * FROM a
2 WHERE a.employee_id IN (SELECT b.employee_id FROM b);

执行计划
----------------------------------------------------------
Plan hash value: 2317816356

---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 217K | 15M| 1375 (2) | 00:00:17 |
|* 1 | HASH JOIN | | 217K | 15M| 1375 (2) | 00:00:17 |
| 2 | SORT UNIQUE | | 217K | 848K| 126 (1) | 00:00:02 |
| 3 | INDEX FAST FULL SCAN | IDX2_B | 217K | 848K| 126 (1) | 00:00:02 |
| 4 | TABLE ACCESS FULL | A | 217K | 14M| 620 (1) | 00:00:08 |
---------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - access("A"."EMPLOYEE_ID"="B"."EMPLOYEE_ID")

可以看出,两个计划完全没有区别。类似于ORACLE查询重写为:
SELECT a.* FROM a,(SELECT DISTINCT b.employee_id FROM b) b1 WHERE a.employee_id=b1.employee_id;

结语:讨论SQL语句:select * from A where id in (1,2,3,4,5,6,7,8,9) 中 在Oracle8i 版本之后的Oracle数据库中性能是一样的。


绥芬河市15987305720: oracle in和exists的区别
帛先肺泰: 一般来说,这两个是用来做两张(或更多)表联合查询用的,in是把外表和内表作hash 连接,而exists 是对外表作loop 循环,假设有A、B两个表,使用时是这样的:1、select * from A where id in (select id from B)--使用in2、select * ...

绥芬河市15987305720: oracle 中 in 和exists用法区别 -
帛先肺泰: 是这样的 in 是返回的结果集 比如你只运行这一句 select sno from sc where cno='c002' 返回的是一列sno 但是exists则不同,返回的是布尔值 虽然里边那个没法单独运行 select * from sc a where cno='c001' and exists(select sno from sc b where cno='c002' and a.sno=b.sno) ; 后边必须要写上两者的关联

绥芬河市15987305720: oracle exists和in的区别 -
帛先肺泰: oracle exists和in的区别 是这样的 in 是返回的结果集 比如你只运行这一句 select sno from sc where cno='c002' 返回的是一列sno

绥芬河市15987305720: oracle中in和exist的区别? -
帛先肺泰: in 和 exists区别in 是把外表和内表作hash join,而exists是对外表作loop,每次loop再对内表进行查询.一直以来认为exists比in效率高的说法是不准确的. 如果查询的两个表大小相当,那么用in和exists差别不大.如果两个表中一个较小,一...

绥芬河市15987305720: oracle数据库中in和exists的详细执行过程 -
帛先肺泰: Exists用于只能用于子查询,可以替代in,若匹配到结果,则退出内部查询,并将条件标志为true,传回全部结果资料,in不管匹配到匹配不到都全部匹配完毕,使用exists可以将子查询结果定为常量,不影响查询效果In和exists对比:若子查询结果集比较小,优先使用in,若外层查询比子查询小,优先使用exists.因为若用in,则oracle会优先查询子查询,然后匹配外层查询,若使用exists,则oracle会优先查询外层表,然后再与内层表匹配.最优化匹配原则,拿最小记录匹配大记录.

绥芬河市15987305720: Oracle SQL的exists与in -
帛先肺泰: 两个用法本来就有区别,IN判断字段的值有没有列表中,列表中的值少的情况下直接用IN,多的情况下建议用JOIN连接;EXISTS条件是判断子查询存在不存在符合的记录,并且只有有一条记录符合条件就判定EXISTS成立.

绥芬河市15987305720: oracle中in和exist的区别 -
帛先肺泰: in和exist的主要区别体现在对sql执行计划的影响上.传统上认为,如果子查询的条件更具选择性(selective),就用in;而如果父查询(外层查询)的条件更具选择性(selective),就用exist.具...

绥芬河市15987305720: oracle数据库里in 和exits 到底有什么区别 -
帛先肺泰: 表A(小表),表B(大表) select * from B where cc in (select cc from A) 这个语句中是先从A表中把cc找出来,然后根据cc再在B中去找相关的cc 由于A表的cc远小于B表的cc 所以可以节省时间 select * from B exists (select cc from A where cc=B.cc)这句话是先从B表里把cc找出来 然后再在A表里找相关的cc 由于B表的cc远多于A表的cc 所以这样做很浪费时间总结: 用in 时 大表在前小表在后用exists时 小表在前大表在后

绥芬河市15987305720: SQL查询中in和exists的区别分析
帛先肺泰: IN 确定给定的值是否与子查询或列表中的值相匹配. EXISTS 指定一个子查询,检测行的存在. 比较使用 EXISTS 和 IN 的查询 这个例子比较了两个语义类似的查询.第一个查询使用 EXISTS 而第二个查询使用 IN.注意两个查询返回相同的信息...

绥芬河市15987305720: SQL语句中“in”和“exist”有什么区别? -
帛先肺泰: 本文主要分析了in和exists的区别与执行效率的问题: 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 ...

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网