oracle 的not in/not exists/in/exists效率对比

前言:没有经过验证的结果都是值得怀疑的
注意:这里的验证,取第二次查询结果

一:先看not in/not exists
这里用scott用户的dept和emp实验
环境oracle 11g,
select * from dept d where d.deptno NOT IN (select deptno from emp ) ;
oracle 的not in/not exists/in/exists效率对比_第1张图片
select * from dept d where not exists ( select deptno from emp where emp.deptno=d.deptno) ;
oracle 的not in/not exists/in/exists效率对比_第2张图片

可以看到:2者的效率是一样的;

如果是oracle10g,那么上面的结果是不一样的; 有10g环境的可以自已验证测试一下
要想not in走ANTI算法,需要加上not null:
select * from dept where deptno NOT IN ( select deptno from emp where deptno is not null) and deptno is not null;
oracle 的not in/not exists/in/exists效率对比_第3张图片

再看看跟数据量有没关系
drop table t1 purge;
drop table t2 purge;
create table t1 as
select * from all_objects where rownum<10000;
create table t2 as
select * from all_objects ;

select * from t2 where t2.object_id not in(select t1.object_id from t1);
oracle 的not in/not exists/in/exists效率对比_第4张图片
select * from t2 where not exists (select 1 from t1 where t1.object_id=t2.object_id);
oracle 的not in/not exists/in/exists效率对比_第5张图片

结论:在oracle 11g,not in和not exists是等价的,跟数据量的大小没关系,都会走ANTI算法;
10g的话,有点区别;

我们再看加了索引呢? 结果还是一样的;
create index t1_ind_id on t1(object_id);
create index t2_ind_id on t2(object_id);
select * from t2 where t2.object_id not in(select t1.object_id from t1);
oracle 的not in/not exists/in/exists效率对比_第6张图片
select * from t2 where not exists (select 1 from t1 where t1.object_id=t2.object_id);
oracle 的not in/not exists/in/exists效率对比_第7张图片
二: in/exists
select * from dept d where d.deptno IN (select deptno from emp ) ;
oracle 的not in/not exists/in/exists效率对比_第8张图片
select * from dept d where exists ( select deptno from emp where emp.deptno=d.deptno) ;
oracle 的not in/not exists/in/exists效率对比_第9张图片
我们发现,2者代价一样;
好,把数据量扩大一下看看跟数据量有没有关系;

drop table t1 purge;
drop table t2 purge;
create table t1 as
select * from all_objects where rownum<10000;
create table t2 as
select * from all_objects ;

select * from t2 where t2.object_id in(select t1.object_id from t1);
oracle 的not in/not exists/in/exists效率对比_第10张图片
select * from t2 where exists (select 1 from t1 where t1.object_id=t2.object_id);
oracle 的not in/not exists/in/exists效率对比_第11张图片
–其实可以用等值连接
select t2.* from t1,t2 where t1.object_id=t2.object_id;
oracle 的not in/not exists/in/exists效率对比_第12张图片

可以发现:in和exists是一样的代价,跟数据量大小没关系,甚至跟等值连接一样;

同理,看看加索引会怎么样
create index t1_ind_id on t1(object_id);
create index t2_ind_id on t2(object_id);
select * from t2 where t2.object_id in(select t1.object_id from t1);
select * from t2 where exists (select 1 from t1 where t1.object_id=t2.object_id);
其实代价也是一样的
oracle 的not in/not exists/in/exists效率对比_第13张图片

有不合理地方,麻烦指正,谢谢

你可能感兴趣的:(数据库)