IN&EXISTS与NOT IN&NOT EXISTS 的优化原则小结

1. EXISTS的执行流程

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。

其实我们区分in和exists主要是造成了驱动顺序的改变(这是性能变化的关键),如果是exists,那么以外层表为驱动表,先被访问,如果是IN,那么先执行子查询,所以我们会以驱动表的快速返回为目标,那么就会考虑到索引及结果集的关系了

另外IN时不对NULL进行处理,如:

select 1 from dual where null in (0,1,2,null)

结果为空。

2. NOT IN 与NOT EXISTS:

NOT EXISTS的执行流程

复制代码 代码如下:

select .....

from rollup R

where not exists ( select 'Found' from title T

where R.source_id = T.Title_ID);

可以理解为:

复制代码 代码如下:

for x in ( select * from rollup )

loop

if ( not exists ( that query ) ) then

OUTPUT

end if;

end;

注意:NOT EXISTS 与 NOT IN 不能完全互相替换,看具体的需求。如果选择的列可以为空,则不能被替换。

例如下面语句,看他们的区别:

select x,y from t;

x y

------ ------

1 3

3 1

1 2

1 1

3 1

5

select * from t where x not in (select y from t t2 )

no rows

select * from t where not exists (select null from t t2

where t2.y=t.x )

x y

------ ------

5 NULL

所以要具体需求来决定

对于not in 和 not exists的性能区别:

not in 只有当子查询中,select 关键字后的字段有not null约束或者有这种暗示时用not in,另外如果主查询中表大,子查询中的表小但是记录多,则应当使用not in,并使用anti hash join.

如果主查询表中记录少,子查询表中记录多,并有索引,可以使用not exists,另外not in最好也可以用/*+ HASH_AJ */或者外连接+is null

NOT IN 在基于成本的应用中较好

比如:

复制代码 代码如下:

select .....

from rollup R

where not exists ( select 'Found' from title T

where R.source_id = T.Title_ID);

改成(佳)

select ......

from title T, rollup R

where R.source_id = T.Title_id(+)

and T.Title_id is null;

或者(佳)

sql> select /*+ HASH_AJ */ ...

from rollup R

where ource_id NOT IN ( select ource_id

from title T

where ource_id IS NOT NULL )

注意:上面只是从理论上提出了一些建议,最好的原则是大家在上面的基础上,能够使用执行计划来分析,得出最佳的语句的写法。

'//=============================

exists,not exists总结

1 exists

SELECT * FROM anken_m WHERE EXISTS(

SELECT my_list_temp_m.sales_code

FROM my_list_temp_m

WHERE my_list_temp_m.sales_code=anken_m.sales_code)

说明:

1) 查询在anken_m表和my_list_temp_m表中都存在的sales_code。

2) sales_code是anken_m的主键,my_list_temp_m的外键。

注意:

1) 外层查询表anken_m是查询的对象。

2) 内层查询表my_list_temp_m是条件对象。

3) 内外层的查询表不能相同。

4) 作为关联条件的anken_m表不需要在内层查询FROM后添加。

5) my_list_temp_m.sales_code=anken_m.sales_code条件的左右顺序不影响查询结果。

2 not exists

SELECT * FROM anken_m WHERE NOT EXISTS(

SELECT my_list_temp_m.sales_code

FROM my_list_temp_m

WHERE my_list_temp_m.sales_code=anken_m.sales_code)

说明:

1) 查询在anken_m表中存在,但是在my_list_temp_m表中不存在的sales_code。

2) sales_code是anken_m的主键,my_list_temp_m的外键。

注意:

1) 外层查询表anken_m是查询的对象。

2) 内层查询表my_list_temp_m是条件对象。

3) 内外层的查询表不能相同。

4) 作为关联条件的anken_m表不需要在内层查询FROM后添加。

5) my_list_temp_m.sales_code=anken_m.sales_code条件的左右顺序不影响查询结果。

3 综合运用

UPDATE anken_m

SET(plan_type_code, branch_name, business_type_code)

=(SELECT anken.plan_type_code,anken.branch_name,anken.business_type_code

FROM anken

WHERE anken.sales_code=anken_m.sales_code)

WHERE EXISTS (

SELECT anken.sales_code

FROM anken,my_list_temp_m

WHERE my_list_temp_m.sales_code=anken.sales_code

AND anken.sales_code=anken_m.sales_code

)

说明:

1) 用一个表的记录数据更新另一个表的记录数据。

2) 用一个SQL语句进行批量更新。

2) sales_code是anken,anken_m的主键,my_list_temp_m的外键。

注意:

1) set 语句中的要被更新字段必须跟数据源字段一一对应,另外数据源查询中的条件必须限定一条记录。也就是根据sales_code可以唯一确定anken的一条记录,和anken_m的一条记录,这样才能保证要被更新的记录和数据源记录的主键是相同的。

2) 根据WHERE EXISTS语句可以确定数据源记录的范围,也就是可以用anken表中哪些记录更新anken_m表。所以anken_m不需要在WHERE EXISTS语句中的FROM后添加。

时间: 2025-01-29 08:14:03

IN&EXISTS与NOT IN&NOT EXISTS 的优化原则小结的相关文章

IN&EXISTS与NOT IN&NOT EXISTS 的优化原则小结_MsSql

1. EXISTS的执行流程 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的性能区别: 如果子查询得出

Oracle In和exists not in和not exists的比较分析_oracle

把这两个很普遍性的网友比较关心的问题总结回答一下. in和exist的区别 从sql编程角度来说,in直观,exists不直观多一个select, in可以用于各种子查询,而exists好像只用于关联子查询 从性能上来看 exists是用loop的方式,循环的次数影响大,外表要记录数少,内表就无所谓了 in用的是hash join,所以内表如果小,整个查询的范围都会很小,如果内表很大,外表如果也很大就很慢了,这时候exists才真正的会快过in的方式. not in和not exists的区别

Exists 方法

    如果 Dictionary 对象中存在所指定的主键则返回 true,否则返回 false. object.Exists(key) 参数 object 必选项.总是一个 Dictionary 对象的名称. key 必选项.需要在 Dictionary 对象中搜索的 key 值. 下面这个例子说明了 Exists 方法的用法. function keyExists(k){   var fso, s = "";   d = new ActiveXObject("Script

源代码-Linux c++ HashMap<bool> exists (false); 的问题

问题描述 Linux c++ HashMap<bool> exists (false); 的问题 HashMap exists (false); 我在看别人写的代码,用grep命令搜索过源代码包后发现这并不是typedef定义的类型,所以请各位大神告诉小弟,这是什么意思 解决方案 会不会是自定义类 再找找 解决方案二: 不是库里面的东西就只能是自定义类了...

SQL查询中in和exists的区别分析_MsSql

select * from A where id in (select id from B); select * from A where exists (select 1 from B where A.id=B.id); 对于以上两种情况,in是在内存里遍历比较,而exists需要查询数据库,所以当B表数据量较大时,exists效率优于in. 1.select * from A where id in (select id from B); in()只执行一次,它查出B表中的所有id字段并缓存

MYSQL IN 与 EXISTS 的优化示例介绍_Mysql

优化原则:小表驱动大表,即小的数据集驱动大的数据集. ############# 原理 (RBO) ##################### select * from A where id in (select id from B) 等价于: for select id from B for select * from A where A.id = B.id 当B表的数据集必须小于A表的数据集时,用in优于exists. select * from A where exists (selec

MySQL关于exists的一个bug_Mysql

今天碰到一个关于exists很奇怪的问题 第一个语句如下: SELECT count(1) FROM APPLY t WHERE EXISTS ( SELECT r.APPLY_ID FROM RECORD r WHERE t.APPLY_ID = r.APPLY_ID ); 产生的结果是:89584 第二个语句如下: SELECT count(1) FROM APPLY t WHERE EXISTS ( SELECT max(r.FINISH_TIME) FROM RECORD r WHERE

SQL SERVER中关于exists 和 in的简单分析_MsSql

In与Exists这两个函数是差不多的,但由于优化方案不同,通常NOT Exists要比NOT IN要快,因为NOT EXISTS可以使用结合算法二NOT IN就不行了,而EXISTS则不如IN快,因为这时候IN可能更多的使用结合算法. 如图,现在有两个数据集,左边表示#tempTable1,右边表示#tempTable2.现在有以下问题: 1.求两个集的交集? 2.求tempTable1中不属于集#tempTable2的集? 先创建两张临时表: create table #tempTable1

sqlserver exists,not exists的用法_MsSql

学生表:create table student( id number(8) primary key, name varchar2(10),deptment number(8)) 选课表:create table select_course(  ID         NUMBER(8) primary key,  STUDENT_ID NUMBER(8) foreign key (COURSE_ID) references course(ID),  COURSE_ID  NUMBER(8) fo