<![endif]--> <![endif]-->

发现公司同事很喜欢用exists 和in 做子查询关联,我觉得很有必要研究下

两者的区别,供参考和备忘

/* (这段信息来自网络begin )对于in 的使用,就相当于对inner table 执行一个带distinct 的子查询,然后将得到的结果集再和outer table 进行外连接,连接方式和索引使用任然同于普通两表的连接(这段信息来自网络end )*/

对于网络的这段描述,我给予了测试,测试表为 liomuser.staff ,和liomuser.department ,这两张表都是小表,数量在1 万左右。

-- 例如:

select *

from liomuser.staff

where department_id in ( select department_id from liomuser.department);

-- 可以转换为

select a.*

from liomuser.staff a,

( select distinct department_id from liomuser.department) b

where a.department_id = b.department_id;

执行计划分别如下:

( 1 ) select *

from liomuser.staff

where department_id in ( select department_id from liomuser.department);

( 2 ) select a.*

from liomuser.staff a,

( select distinct department_id from liomuser.department) b

where a.department_id = b.department_id;

我选择的是两个小表,从数据上看采用外连接的方式除了一致性读要稍微小一点,两者执行计划和统计信息几乎一样。

测试结果显示对于小表网络上给出的描述是正确的

但是以我的经验,in 的方式应该比外连接性能要差很多,按照上面的测试,两者似乎是一样的执行路径,是不是应为表数据量少的缘故呢?

我决定采用两张大表做测试,cust_order 和order_detail 这两张表的数据量都在一千万以上。

首先测试in ,语句如下:

select a.*

from liomuser.cust_order a

where order_id in ( select order_id from liomuser.order_detail b);

执行计划如下:

测试2 外连接,语句如下:

select a.*

from liomuser.cust_order a,

( select distinct order_id from liomuser.order_detail) b

where a.order_id = .order_id ;

执行计划如下:

对着两个大表的in 和外连接的对比可以看出,采用外连接的执行计划明显优于in 的方式,采用in方式则表连接采用nested loop 方式,而外连接采用了HASH JOIN ,

并且in 方式的CPUcost 要比外连接大1/3, 这样看来,对于小表,或者说inner table 是小表的查询,in 和外连接都差不多,但是对于大表,特别是inner table 数据量巨大的时候,采用外连接要好很多。

由此看出,in 并不完全等同于与inner table 做distinct 外连接,但是外连接要比in 有效率得多。

下面讨论下 EXIST

实际上exists 等同于先对outer table 进行扫描,从中检索到每行和inner table 做循环匹配,执行计划如下:

注释:部分网上资料认为exists 对outer table 会进行全表扫描,但是在该执行计划中没有发现全表扫描,仍然走了索引。

Exists 的写法可以转换成:

declare cnt number ( 10 );

for cur in ( select a.*  from liomuser.cust_order a) loop

cnt:= 0 ;

select count ( 1 ) into cnt from liomuser.order_detail where order_id=cur.order_id;

if cnt<> 0 then

return cur;

end if ;

end loop ;

exists 与 in 的比对:

语句 1 , in

语句 2 , exsits

从执行计划上来看没有任何区别,再让我们看看执行的统计信息:

语句 1 , in

select a.*

from liomuser.cust_order a

where order_id in ( select order_id from liomuser.order_detail b)

语句 2 , exists

select a.*

from liomuser.cust_order a

where exists

( select 1 from liomuser.order_detail b where a.order_id = b.order_id)

从两种方式统计信息可以看出,采用 exists 的一致性读要比 in 要好,但是 bytessent 要比 in高,这个也从侧面验证了前面所说的 exists 相当于 loop

 

通过上面解释现在很容易明白当 inner table 数据量巨大且索引情况不好 ( 大量重复值等 ) 则不宜使用产生对 inner table 检索而导致系统开支巨大 IN 操作,建议对 innertable 过大的查询,采取 exsits ,或者外连接方式

另外: NOT IN 子句将执行个内部排序和合并 . 无论在哪种情况下 ,NOT IN 都是

最低效 ( 它对子查询中表执行了个全表遍历 ). 为了避免使用 NOT IN , 我们可以把它改写成外连接 (Outer Joins) 或 NOT EXISTS

plsql exist和in 的区别的更多相关文章

  1. PLSQL oracle32位 oracle64 安装区别及注意问题

    一.先明确几个概念: 1.PLSQL 只有32位的. 2.oracle 客户端 分别有32.64位,一般使用32位. 3.oracle 服务端 分别有32.64位,一般老的服务器使用32位,新的服务器 ...

  2. Mysql的exist与in的区别

    如果查询的两个表大小相当,那么用in和exists差别不大. 如果两个表中一个较小,一个是大表,则子查询表大的用exists,子查询表小的用in:    例如:表A(小表),表B(大表)   1: s ...

  3. 常用SQL语句优化技巧

    除了建立索引之外,保持良好的SQL语句编写习惯将会降低SQL性能问题发生. ①通过变量的方式来设置参数 好:stringsql = "select * from people p where ...

  4. 总结一些php的面试题

    1.PHP语言的一大优势是跨平台,什么是跨平台?一.PHP基础: PHP的运行环境最优搭配为Apache+MySQL+PHP,此运行环境可以在不同操作系统(例如windows.Linux等)上配置,不 ...

  5. php面试题汇总四(基础篇附答案)

    1. 什么事面向对象?主要特征是什么? 面向对象是程序的一种设计方式,它利于提高程序的重用性,使程序结构更加清晰.主要特征:封装.继承.多态. 2. SESSION 与 COOKIE的区别是什么,请从 ...

  6. 邓_php面试【003】——完整版

    php面试题汇总四(基础篇附答案) 1. 什么事面向对象?主要特征是什么? 面向对象是程序的一种设计方式,它利于提高程序的重用性,使程序结构更加清晰.主要特征:封装.继承.多态. 2. SESSION ...

  7. oracle逐步学习总结之约束(基础五)

    原创作品,转自请在文章明显位置注明出处:https://www.cnblogs.com/sunshine5683/p/10167717.html oracle中的约束主要有非空约束(not null) ...

  8. 安装64位的oracle数据库, 使用自带的sqldeveloper

    个人感觉这个东西比plsql要好用, 虽然界面有点丑, 整个使用与plsql也没多大区别, 这里是他的位置C:\oracle_11g\product\11.2.0\dbhome_1\sqldevelo ...

  9. 很有用的PHP笔试题系列三

    1. 什么事面向对象?主要特征是什么? 面向对象是程序的一种设计方式,它利于提高程序的重用性,使程序结构更加清晰.主要特征:封装.继承.多态. 2. SESSION 与 COOKIE的区别是什么,请从 ...

随机推荐

  1. 在页面生命周期执行时 Page 对象在 SaveState 阶段都发生了什么事?

    先看下 SaveViewState 的源码: // Answer any state this control or its descendants want to save on freeze. / ...

  2. 九度OJ 1510 替换空格

    题目地址:http://ac.jobdu.com/problem.php?pid=1510 题目描述: 请实现一个函数,将一个字符串中的空格替换成"%20".例如,当字符串为We ...

  3. OpenJudge / Poj 1003 Hangover

    链接地址: Poj:http://poj.org/problem?id=1003 OpenJudge:http://bailian.openjudge.cn/practice/1003 题目: Han ...

  4. Headfirst设计模式的C++实现——外观模式(Facade)

    light.h #ifndef _LIGHT_H_ #define _LIGHT_H_ #include <iostream> class LIGHT { public: void dim ...

  5. NSInteger 与 NSUInteger 和 int与 NSInteger 区别(转)

    转自:http://blog.csdn.net/duxinfeng2010/article/details/7606261 先说说NSInteger 与 NSUInteger,在看书上代码是遇见NSI ...

  6. Web前端新人笔记之文本属性

    前一段时间因工作时间减缓了更新笔记的时间.我也不知道有没有会观看并且能不能帮到一些初学者,这只是我的一些小随笔而已.当然我也希望的的每一篇随笔都可以帮到更多的想要学习前端开发的初学者们,更希望你们也可 ...

  7. 用EPPlus导入导出数据到excel

    项目上中要用到将数据库中所有表导出为Excel,以及将Excel数据导入数据库中的操作,使用EPPlus组件,编写以下两个函数. using OfficeOpenXml;using OfficeOpe ...

  8. SQL获取数据库中表的列名和列类型

    select column_name as [字段名],data_type as [数据类型] from information_schema.columns where table_name='表名 ...

  9. spring data mongodb中,如果对象中的属性不想加入到数据库字段中

    spring data mongodb中,如果对象中的属性不想加入到数据库字段中,可加@Transient注解,声明为透明属性 spring data mongodb 官网帮助文档 http://ww ...

  10. PHP LINUX Notice: undefined $_GET完美解决方法

    PHP Notice: undefined 平时用$_GET[‘xx’] 取得参数值时,如果之前不加判断在未传进参数时会出现这样的警告: PHP Notice: undefined index xxx ...