[20180808]exists and not exists.txt
[20180808]exists and not exists.txt
--//生产系统遇到的一个性能问题,通过例子来说明:
1.环境:
SCOTT@test01p> @ ver1
PORT_STRING VERSION BANNER CON_ID
------------------------------ -------------- -------------------------------------------------------------------------------- ----------
IBMPC/WIN_NT64-9.1.0 12.1.0.1.0 Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production 0
SCOTT@test01p> create table t1 as select * from all_objects;
Table created.
SCOTT@test01p> create table t2 as select object_id,'1' flag from t1;
Table created.
SCOTT@test01p> select max(object_id) from t2;
MAX(OBJECT_ID)
--------------
107828
SCOTT@test01p> update t2 set flag='0' where object_id=107828;
1 row updated.
SCOTT@test01p> commit ;
Commit complete.
SCOTT@test01p> create index i_t2_flag on t2(flag);
Index created.
--//分析表,并且t2的flag字段建立直方图.
execute sys.dbms_stats.gather_table_stats ( OwnName => user,TabName => 't1',Estimate_Percent => NULL,Method_Opt => 'FOR ALL COLUMNS SIZE 1 ',Cascade => True ,No_Invalidate => false);
execute sys.dbms_stats.gather_table_stats ( OwnName => user,TabName => 't2',Estimate_Percent => NULL,Method_Opt => 'FOR ALL COLUMNS SIZE 1 for columns flag size 10 ',Cascade => True ,No_Invalidate => false);
`
2.测试:
SCOTT@test01p> alter session set statistics_level=all;
Session altered.
SCOTT@test01p> select object_name from t1 where not exists (select 1 from t2 where t2.object_id=t1.object_id and t2.flag='1' );
OBJECT_NAME
--------------------
T1
SCOTT@test01p> @ dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID d4qcxhmwy49r1, child number 0
-------------------------------------
select object_name from t1 where not exists (select 1 from t2 where
t2.object_id=t1.object_id and t2.flag='1' )
Plan hash value: 629543484
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows |E-Bytes|E-Temp | Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers | Reads | OMem | 1Mem | Used-Mem |
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | | | 728 (100)| | 1 |00:00:00.24 | 1667 | 1511 | | | |
|* 1 | HASH JOIN RIGHT ANTI| | 1 | 899 | 33263 | 1672K| 728 (1)| 00:00:01 | 1 |00:00:00.24 | 1667 | 1511 | 5536K| 3056K| 5658K (0)|
|* 2 | TABLE ACCESS FULL | T2 | 1 | 89876 | 614K| | 46 (3)| 00:00:01 | 89876 |00:00:00.02 | 152 | 0 | | | |
| 3 | TABLE ACCESS FULL | T1 | 1 | 89877 | 2633K| | 421 (1)| 00:00:01 | 89877 |00:00:00.11 | 1515 | 1511 | | | |
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$5DA710D3
2 - SEL$5DA710D3 / T2@SEL$2
3 - SEL$5DA710D3 / T1@SEL$1
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("T2"."OBJECT_ID"="T1"."OBJECT_ID")
2 - filter("T2"."FLAG"='1')
--//仔细看id-2.过滤条件是 2 - filter("T2"."FLAG"='1').这样即使你建立索引在t2.flag也不会使用.因为flag='1'占大多数.
--//实际上对于当前应用改成如下是等效的.因为flag仅仅两种取值'0','1'.
SCOTT@test01p> select object_name from t1 where exists (select 1 from t2 where t2.object_id=t1.object_id and t2.flag='0' );
OBJECT_NAME
--------------------
T1
SCOTT@test01p> @ dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID 1y5xvtwz0u11f, child number 0
-------------------------------------
select object_name from t1 where exists (select 1 from t2 where
t2.object_id=t1.object_id and t2.flag='0' )
Plan hash value: 1273788863
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers | Reads | OMem | 1Mem | Used-Mem |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | | 423 (100)| | 1 |00:00:00.19 | 1518 | 1512 | | | |
|* 1 | HASH JOIN RIGHT SEMI | | 1 | 1 | 37 | 423 (1)| 00:00:01 | 1 |00:00:00.19 | 1518 | 1512 | 2168K| 2168K| 697K (0)|
| 2 | TABLE ACCESS BY INDEX ROWID BATCHED| T2 | 1 | 1 | 7 | 2 (0)| 00:00:01 | 1 |00:00:00.04 | 3 | 1 | | | |
|* 3 | INDEX RANGE SCAN | I_T2_FLAG | 1 | 1 | | 1 (0)| 00:00:01 | 1 |00:00:00.04 | 2 | 1 | | | |
| 4 | TABLE ACCESS FULL | T1 | 1 | 89877 | 2633K| 421 (1)| 00:00:01 | 89877 |00:00:00.12 | 1515 | 1511 | | | |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$5DA710D3
2 - SEL$5DA710D3 / T2@SEL$2
3 - SEL$5DA710D3 / T2@SEL$2
4 - SEL$5DA710D3 / T1@SEL$1
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("T2"."OBJECT_ID"="T1"."OBJECT_ID")
3 - access("T2"."FLAG"='0')
--//实际上到具体应用object_id字段是主键,如果在上面建立索引,逻辑读更小.
CREATE UNIQUE INDEX SCOTT.pk_t1 ON SCOTT.T1 (OBJECT_ID);
ALTER TABLE SCOTT.T1 ADD CONSTRAINT pk_t1 PRIMARY KEY (OBJECT_ID);
CREATE UNIQUE INDEX SCOTT.pk_t2 ON SCOTT.T2 (OBJECT_ID);
ALTER TABLE SCOTT.T2 ADD CONSTRAINT pk_t2 PRIMARY KEY (OBJECT_ID);
SCOTT@test01p> select object_name from t1 where exists (select 1 from t2 where t2.object_id=t1.object_id and t2.flag='0' );
OBJECT_NAME
--------------------
T1
SCOTT@test01p> @ dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID 1y5xvtwz0u11f, child number 0
-------------------------------------
select object_name from t1 where exists (select 1 from t2 where
t2.object_id=t1.object_id and t2.flag='0' )
Plan hash value: 4193600567
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers | Reads | OMem | 1Mem | Used-Mem |
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | | 3 (100)| | 1 |00:00:00.04 | 6 | 2 | | | |
| 1 | NESTED LOOPS | | 1 | | | | | 1 |00:00:00.04 | 6 | 2 | | | |
| 2 | NESTED LOOPS | | 1 | 1 | 37 | 3 (0)| 00:00:01 | 1 |00:00:00.03 | 5 | 1 | | | |
| 3 | SORT UNIQUE | | 1 | 1 | 7 | 2 (0)| 00:00:01 | 1 |00:00:00.01 | 3 | 0 | 2048 | 2048 | 2048 (0)|
| 4 | TABLE ACCESS BY INDEX ROWID BATCHED| T2 | 1 | 1 | 7 | 2 (0)| 00:00:01 | 1 |00:00:00.01 | 3 | 0 | | | |
|* 5 | INDEX RANGE SCAN | I_T2_FLAG | 1 | 1 | | 1 (0)| 00:00:01 | 1 |00:00:00.01 | 2 | 0 | | | |
|* 6 | INDEX UNIQUE SCAN | PK_T1 | 1 | 1 | | 0 (0)| | 1 |00:00:00.03 | 2 | 1 | | | |
| 7 | TABLE ACCESS BY INDEX ROWID | T1 | 1 | 1 | 30 | 1 (0)| 00:00:01 | 1 |00:00:00.01 | 1 | 1 | | | |
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
4 - SEL$5DA710D3 / T2@SEL$2
5 - SEL$5DA710D3 / T2@SEL$2
6 - SEL$5DA710D3 / T1@SEL$1
7 - SEL$5DA710D3 / T1@SEL$1
Predicate Information (identified by operation id):
---------------------------------------------------
5 - access("T2"."FLAG"='0')
6 - access("T2"."OBJECT_ID"="T1"."OBJECT_ID")
Note
-----
- this is an adaptive plan
--//而select object_name from t1 where not exists (select 1 from t2 where t2.object_id=t1.object_id and t2.flag='1' );执行计划不变.不再贴出.
--//我有时候想开发写sql代码过脑子没有,有时候真的很无语很无奈...
[20180808]exists and not exists.txt的更多相关文章
- 转【】浅谈sql中的in与not in,exists与not exists的区别_
浅谈sql中的in与not in,exists与not exists的区别 1.in和exists in是把外表和内表作hash连接,而exists是对外表作loop循环,每次loop循环再对内表 ...
- 浅谈sql中的in与not in,exists与not exists的区别
转 浅谈sql中的in与not in,exists与not exists的区别 12月12日北京OSC源创会 —— 开源技术的年终盛典 » sql exists in 1.in和exists ...
- MySQL 子查询 EXISTS 和 NOT EXISTS(转)
MySQL EXISTS 和 NOT EXISTS 子查询 MySQL EXISTS 和 NOT EXISTS 子查询语法如下: SELECT ... FROM table WHERE EXISTS ...
- MySQL 子查询 EXISTS 和 NOT EXISTS
MySQL EXISTS 和 NOT EXISTS 子查询 MySQL EXISTS 和 NOT EXISTS 子查询语法如下: SELECT ... FROM table WHERE EXISTS ...
- oracle中的exists 和not exists 用法 in与exists语句的效率问题
博文来源(oracle中的exists 和not exists 用法):http://chenshuai365-163-com.iteye.com/blog/1003247 博文来源( in与exi ...
- (转)sql中 in 、not in 、exists、not exists 用法和差别
exists (sql 返回结果集为真) not exists (sql 不返回结果集为真) 如下: 表A ID NAME 1 A1 2 A2 3 A3 表B ID AI ...
- Mysql数据库中的EXISTS和NOT EXISTS
SQL语言中没有蕴含逻辑运算.但是,可以利用谓词演算将一个逻辑蕴含的谓词等价转换为:p->q ≡┐p∨q. 我们通过一个具体的题目来分析:(具体的表和数据详见文章:Mysql数据库中的EXIST ...
- sql中 in 、not in 、exists、not exists 使用方法和区别
% 的一类. NOT IN:通过 NOT IN keyword引入的子查询也返回一列零值或很多其它值. 以下查询查找没有出版过商业书籍的出版商的名称. SELECT pub_name FROM pub ...
- C#中当程序的访问权限不足时,Directory.Exists和File.Exists方法不会抛出异常报错
有些时候,我们开发的C#应用程序的执行账号,可能没有对一些文件夹和文件的访问权限,当我们使用Directory.Exists和File.Exists方法去判断这些文件夹和文件是否存在的时候,Direc ...
随机推荐
- solr(六): 集群
前言 随着用户的增多,空间和并发量越来越多,会导致一台solr服务器干不过了.这时候,就需要将solr集群以下. 集群架构 由多台服务器共同完成索引和搜索任务 实现的思路是将索引数据进行shard(分 ...
- How Tomcat works — 二、tomcat启动(1)
主要介绍tomcat启动涉及到的一些接口和类. 目录 概述 tomcat包含的组件 server和service Lifecycle Container Connector 总结 概述 tomcat作 ...
- 【原创】Python第二章——标识符命名规则
在Python中,一切都是对象,包括常量数据类型,如整数数据类型(1,2,3...),字符串数据类型("ABC").想要使用这些对象,就要使用它的对象引用.赋值操作符,实际上是使得 ...
- 飞跃式发展的后现代 Python 世界
飞跃式发展的后现代Python世界 如果现代Python有一个标志性特性,那么简单说来便是Python对自身定义的越来越模糊.在过去的几年的许多项目都极大拓展了Python,并重建了“Python”本 ...
- Java设计模式学习记录-模板方法模式
前言 模板方法模式,定义一个操作中算法的骨架,而将一些步骤延迟到子类中.使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤. 模板方法模式 概念介绍 模板方法模式,其实是很好理解的,具体 ...
- 【Go】优雅的读取http请求或响应的数据
[Go]优雅的读取http请求或响应的数据 原文链接:https://blog.thinkeridea.com/201901/go/you_ya_de_du_qu_http_qing_qiu_huo_ ...
- Linux tee的花式用法和pee
1.tee多重定向 tee [options] FILE1 FILE2 FILE3... tee的作用是将一份标准输入多重定向,一份重定向到标准输出/dev/stdout,然后还将标准输入重定向到每个 ...
- mac os下vscode快捷键
全局 Command + Shift + P / F1 显示命令面板 Command + P 快速打开 Command + Shift + N 打开新窗口 Command + W 关闭窗口 基本 Co ...
- vim之添加多行和删除多行
1.复制单行和多行. 1)单行复制 在命令模式下,将光标移到将要复制的行处,按“yy”进行复制,按“p”进行粘贴. 2)多行复制 在命令模式下,将光标移到将要复制的行处,按“nyy”进行复制(n代表行 ...
- GVRP 的工作机制和工作模式
GVRP 简介 GVRP 基于 GARP 的工作机制来维护设备中的 VLAN 动态注册信息,并将该信息向其他设备传播:当设备启动了 GVRP 之后,就能够接收来自其他设备的 VLAN 注册信息,并动态 ...