oracle中的exists和not exists和in用法详解
in 是把外表和内表作hash 连接,而exists是对外表作loop循环,每次loop循环再对内表进行查询。
not exists:做NL,对子查询先查,有个虚表,有确定值,所以就算子查询有NULL最终也有值返回
not in:做hash,对子查询表建立内存数组,用外表匹配,那子查询要是有NULL那外表没的匹配最终无值返回。
一直以来认为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列的索引。
not in 和not exists
如果查询语句使用了not in 那么内外表都进行全表扫描,没有用到索引; 而not extsts 的子查询依然能用到表上的索引。 所以无论那个表大,用not exists都比not in要快。
一直听到的都是说尽量用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 关联子查询与非关联子查询
关联子查询需要在内部引用外部表,而非关联子查询不要引用外部表。对于父查询中处理的记录来说,一个关联子查询是每行计算一次,然而一个非关联子查询只会执行一次,而且结果集被保存在内存中(如果结果集比较小),或者放在一张oracle临时数据段中(如果结果集比较大)。一个“标量”子查询是一个非关联子查询,返回唯一记录。如果子查询仅仅返回一个记录,那么oracle优化器会将结果缩减为一个常量,而且这个子查询只会执行一次。 /*select * from emp where deptno in (select deptno from dept where dept_name='admin');*/ 2.如何选择? 根据外部查询,以及子查询本身所返回的记录的数目。如果两种查询返回的结果是相同的,哪一个效率更好?
关联子查询的系统开销:对于返回到外层查询的记录来说,子查询会每次执行一次。因此,必须保证任何可能的时候子查询都要使用索引。
非关联子查询的系统开销:子查询只会执行一次,而且结果集通常是排好序的,并保存在临时数据段中,其中每一个记录在返回时都会被父级查询引用,在子查询返回大量记录的情况下,将这些结果集排序回增大系统的开销。
所以:如果父查询只返回较少的记录,那么再次执行子查询的开销不会非常大,如果返回很多数据行,那么直查询就会执行很多次。 如果子查询返回较少的记录,那么为内存中保存父查询的结果集的系统开销不会非常大,如果子查询返回多行,那么需要将结果放在临时段上,然后对数据段排序,以便为负查询中的每个记录服务。
3结论:1)在使用一个关联子查询是,使用in 或者 exists子句的子查询执行计划通常都相同
2)exists子句通常不适于子查询
3)在外部查询返回相对较少记录时,关联子查询比非关联子查询执行得要更快。 4)如果子查询中只有少量的记录,则非关联子查询会比关联子查询执行得更快。 4 子查询转化:子查询可以转化为标准连接操作 1)使用in的非关联子查询(子查询唯一)
条件:1)在整个层次结构中最底层数据表上定义唯一主键的数据列存在于子查询的select列表中
2)至少有个定义了唯一主键的数据列在select列表中,而且定义唯一主键的其他数据列都必须有指定的相等标准,不管是直接指定,还是间接指定。 2)使用exists子句的关联子查询
条件:对于相关条件来说,该子查询只能返回一个记录。
5。not in和not exists调整
1)not in 非关联子查询:转化为in写法下的minus子句
2)not exists关联子查询:这种类型的反连接操作会为外部查询中每一个记录进行内部查询,除了不满足子查询中where条件的内部数据表以外,他会过滤掉所有记录。 可以重写:在一个等值连接中指定外部链接条件,然后添加select distinct eg:select distinct ... from a,b where a.col1 = b.col1(+) and b.col1 is null 6。在子查询中使用all any
oracle中的exists和not exists和in用法详解的更多相关文章
- Android 中 View移动总结:ViewDragHelper学习及用法详解
如上图简单呈现出两个方块后,提出一个需求: 1.拖动方块时,方块(即子View)可以跟随手指移动. 2.一个方块移动时,另一个方块可以跟随移动. 3.将方块移动到左边区域(右边区域)后放开(即手指离开 ...
- js中 call() 和 apply() 方法的区别和用法详解
1.定义 每个函数都包含俩个非继承而来的方法:call() 和 apply() call 和 apply 可以用来重新定义函数的的执行环境,也就是 this 的指向:call 和 apply 都是 ...
- sql: sybase与oracle中insert into select和select into的用法
1. sybase与oracle中insert into select和select into的用法 http://wjlvivid.iteye.com/blog/1921679 Sybase 一.首 ...
- Oracle数据库中序列(SEQUENCE)的用法详解
Oracle数据库中序列(SEQUENCE)的用法详解 在Oracle数据库中,序列的用途是生成表的主键值,可以在插入语句中引用,也可以通过查询检查当前值,或使序列增至下一个值.本文我们主要介绍了 ...
- mysql中event的用法详解
一.基本概念mysql5.1版本开始引进event概念.event既“时间触发器”,与triggers的事件触发不同,event类似与linux crontab计划任务,用于时间触发.通过单独或调用存 ...
- Oracle 11g客户端在Linux系统上的配置步骤详解
Oracle 11g客户端在Linux系统上的配置步骤详解 2011-07-26 10:47 newhappy2008 CSDN博客 字号:T | T 本文我们主要介绍了Oracle 11g客户端在L ...
- oracle正则表达式regexp_like的用法详解
oracle正则表达式regexp_like的用法详解 /*ORACLE中的支持正则表达式的函数主要有下面四个:1,REGEXP_LIKE :与LIKE的功能相似2,REGEXP_INSTR :与IN ...
- oracle数据库定时任务dbms_job的用法详解
本文来源:Ruthless <oracle数据库定时任务dbms_job的用法详解> 一.dbms_job涉及到的知识点 1.创建job: variable jobno number; ...
- oracle expdp/impdp 用法详解
http://hi.baidu.com/hzfsai/item/4a4b3fc4b1cf7e51ad00efbd oracle expdp/impdp 用法详解 Data Pump 反映了整个导出/导 ...
- C#中string.format用法详解
C#中string.format用法详解 本文实例总结了C#中string.format用法.分享给大家供大家参考.具体分析如下: String.Format 方法的几种定义: String.Form ...
随机推荐
- wsgi 简介
原文博客地址 http://blog.csdn.net/on_1y/article/details/18803563
- CI(CodeIgniter)框架中的增删改查操作
我们创建一个模型( 项目目录/models/),请注意:模型名与文件名相同且必须继承数据核心类CI_Model,同时重载父类中的构造方法 CodeIgniter的数据函数类在 \models\User ...
- Biorhythms(poj 1006)
Description 人生来就有三个生理周期,分别为体力.感情和智力周期,它们的周期长度为23天.28天和33天.每一个周期中有一天是高峰.在高峰这天,人会在相应的方面表现出色.例如,智力周期的高峰 ...
- 了不得,我可能发现了Jar 包冲突的秘密
一.前言 这篇是类加载器相关的第三篇: 实战分析Tomcat的类加载器结构(使用Eclipse MAT验证) 还是Tomcat,关于类加载器的趣味实验 昨天下午刚写了篇 类加载器相关的,晚上想着验证个 ...
- GDOI2018 新的征程
看标题您一定以为考得很好.. Bad ending.想看美好结局的出门右转其他大佬博客. Day0 早上去车站的时候心情挺好.倒不是因为自己做足了准备,也不是因为预感到有好事发生,而是心情不好也没有用 ...
- 【黑科技】读写优化 orz bdd
转自 bdd :http://www.cnblogs.com/kevince/p/3924688.html 读入优化: inline int read() { char ch; bool flag = ...
- Eclipse 语言文件下载地址
http://www.eclipse.org/babel/downloads.php 更改配色: 安装新软件: http://eclipse-color-theme.github.com/update
- 记住密码后,密码框Password会自动带出数据
一般登陆之后浏览器会询问是否记住密码,如果把密码记住在浏览器上,下次登陆的时候浏览器会把用户名和密码自动填充到登录页面.前段时间服务站平台的员工账号模块提测后,测试提出360浏览器记住密码后会自用把登 ...
- ROS下使用ASUS Xtion Pro Live
一.ROS官网hydro版本OpenNI安装 3. Installation 3.1 Ubuntu installation To install only openni_camera: sudo a ...
- IO重定向
http://tldp.org/LDP/abs/html/io-redirection.html http://mp.weixin.qq.com/s/JMHDutEG4R0hEaXrYPmCGg 每个 ...