plsql exist和in 的区别
<![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 的区别的更多相关文章
- PLSQL oracle32位 oracle64 安装区别及注意问题
一.先明确几个概念: 1.PLSQL 只有32位的. 2.oracle 客户端 分别有32.64位,一般使用32位. 3.oracle 服务端 分别有32.64位,一般老的服务器使用32位,新的服务器 ...
- Mysql的exist与in的区别
如果查询的两个表大小相当,那么用in和exists差别不大. 如果两个表中一个较小,一个是大表,则子查询表大的用exists,子查询表小的用in: 例如:表A(小表),表B(大表) 1: s ...
- 常用SQL语句优化技巧
除了建立索引之外,保持良好的SQL语句编写习惯将会降低SQL性能问题发生. ①通过变量的方式来设置参数 好:stringsql = "select * from people p where ...
- 总结一些php的面试题
1.PHP语言的一大优势是跨平台,什么是跨平台?一.PHP基础: PHP的运行环境最优搭配为Apache+MySQL+PHP,此运行环境可以在不同操作系统(例如windows.Linux等)上配置,不 ...
- php面试题汇总四(基础篇附答案)
1. 什么事面向对象?主要特征是什么? 面向对象是程序的一种设计方式,它利于提高程序的重用性,使程序结构更加清晰.主要特征:封装.继承.多态. 2. SESSION 与 COOKIE的区别是什么,请从 ...
- 邓_php面试【003】——完整版
php面试题汇总四(基础篇附答案) 1. 什么事面向对象?主要特征是什么? 面向对象是程序的一种设计方式,它利于提高程序的重用性,使程序结构更加清晰.主要特征:封装.继承.多态. 2. SESSION ...
- oracle逐步学习总结之约束(基础五)
原创作品,转自请在文章明显位置注明出处:https://www.cnblogs.com/sunshine5683/p/10167717.html oracle中的约束主要有非空约束(not null) ...
- 安装64位的oracle数据库, 使用自带的sqldeveloper
个人感觉这个东西比plsql要好用, 虽然界面有点丑, 整个使用与plsql也没多大区别, 这里是他的位置C:\oracle_11g\product\11.2.0\dbhome_1\sqldevelo ...
- 很有用的PHP笔试题系列三
1. 什么事面向对象?主要特征是什么? 面向对象是程序的一种设计方式,它利于提高程序的重用性,使程序结构更加清晰.主要特征:封装.继承.多态. 2. SESSION 与 COOKIE的区别是什么,请从 ...
随机推荐
- HW-IP合法性_Java
描述 现在IPV4下用一个32位无符号整数来表示,一般用点分方式来显示,点将IP地址分成4个部分,每个部分为8位,表示成一个无符号整数(因此不需要用正号出现),如10.137.17.1,是我们非常熟悉 ...
- 浅析foreach原理
在日常开发工作中,我们发现很多对象都能通过foreach来遍历,比如HashTable.Dictionary.数组等数据类型.那为何这些对象能通过foreach来遍历呢?如果写一个普通的Person类 ...
- OpenJudge / Poj 1044 Date bugs C++
链接地址: Poj:http://poj.org/problem?id=1044 OpenJudge:http://bailian.openjudge.cn/practice/1044/ 题目: 总时 ...
- Eclipse配置CAS client
1.新建一个Maven项目 2.Next,选择 3.输入group id 和 artifact id --> Finish 4.项目创建完成的目录结构 编辑pom.xml文件,写上依赖 注意把 ...
- RX编程笔记——JavaScript 获取地理位置
RX编程笔记——JavaScript 获取地理位置 2016-07-05
- MongoDB入门三步曲1--安装、基本操作
mongodb 基本操作 目录 mongodb安装 mongod启动 mongo shell启动 mongod 停止 mongodb基本操作:CRUD 数据插入 数据查询 数据更新 数据删除 集合删除 ...
- 51nod1242 斐波那契数列 矩阵快速幂
1242 斐波那契数列的第N项 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 #include<stdio.h> #define mod 100000000 ...
- 为什么Laravel是最成功的PHP框架?
Laravel 是一个有着美好前景的年轻框架,它的社区充满着活力,相关的文档和教程完整而清晰,并为快速.安全地开发现代应用程序提供了必要的功能.在近几年对PHP 框架流行度的统计中,Laravel始终 ...
- 《Effective Java》读书笔记
一.引言 1.几条基本规则:(清晰性和简洁性最为重要) 模块的用户永远也不应该被模块的行为所迷惑(那样就不清晰了),模块要尽可能小,但又不能太小 代码应该被重用,而不是被拷贝 模块之间的依赖性应该尽可 ...
- How to open .ccproj in VS2010?
Q: How to open .ccproj projects types in VS2010, ccproj file type is a Cloud project i suppose. Plea ...