[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的更多相关文章

  1. 转【】浅谈sql中的in与not in,exists与not exists的区别_

    浅谈sql中的in与not in,exists与not exists的区别   1.in和exists in是把外表和内表作hash连接,而exists是对外表作loop循环,每次loop循环再对内表 ...

  2. 浅谈sql中的in与not in,exists与not exists的区别

    转 浅谈sql中的in与not in,exists与not exists的区别   12月12日北京OSC源创会 —— 开源技术的年终盛典 »   sql exists in 1.in和exists ...

  3. MySQL 子查询 EXISTS 和 NOT EXISTS(转)

    MySQL EXISTS 和 NOT EXISTS 子查询 MySQL EXISTS 和 NOT EXISTS 子查询语法如下: SELECT ... FROM table WHERE EXISTS ...

  4. MySQL 子查询 EXISTS 和 NOT EXISTS

    MySQL EXISTS 和 NOT EXISTS 子查询 MySQL EXISTS 和 NOT EXISTS 子查询语法如下: SELECT ... FROM table WHERE EXISTS ...

  5. oracle中的exists 和not exists 用法 in与exists语句的效率问题

    博文来源(oracle中的exists 和not exists 用法):http://chenshuai365-163-com.iteye.com/blog/1003247 博文来源(  in与exi ...

  6. (转)sql中 in 、not in 、exists、not exists 用法和差别

    exists (sql 返回结果集为真)  not exists (sql 不返回结果集为真)  如下:  表A  ID NAME  1    A1  2    A2  3  A3 表B  ID AI ...

  7. Mysql数据库中的EXISTS和NOT EXISTS

    SQL语言中没有蕴含逻辑运算.但是,可以利用谓词演算将一个逻辑蕴含的谓词等价转换为:p->q ≡┐p∨q. 我们通过一个具体的题目来分析:(具体的表和数据详见文章:Mysql数据库中的EXIST ...

  8. sql中 in 、not in 、exists、not exists 使用方法和区别

    % 的一类. NOT IN:通过 NOT IN keyword引入的子查询也返回一列零值或很多其它值. 以下查询查找没有出版过商业书籍的出版商的名称. SELECT pub_name FROM pub ...

  9. C#中当程序的访问权限不足时,Directory.Exists和File.Exists方法不会抛出异常报错

    有些时候,我们开发的C#应用程序的执行账号,可能没有对一些文件夹和文件的访问权限,当我们使用Directory.Exists和File.Exists方法去判断这些文件夹和文件是否存在的时候,Direc ...

随机推荐

  1. ES6 系列之私有变量的实现

    前言 在阅读 <ECMAScript 6 入门>的时候,零散的看到有私有变量的实现,所以在此总结一篇. 1. 约定 实现 class Example { constructor() { t ...

  2. spring-boot-2.0.3启动源码篇一 - SpringApplication构造方法

    前言 spring-boot-2.0.3应用篇 - shiro集成,实现了spring-boot与shiro的整合,效果大家也看到了,工程确实集成了shiro的认证与授权功能.如果大家能正确搭建起来, ...

  3. 第7章 Linux上配置RAID

    7.1 RAID概念 RAID独立磁盘冗余阵列(Redundant Array of Independent Disks),RAID技术是将许多块硬盘设备组合成一个容量更大.更安全的硬盘组,可以将数据 ...

  4. 数据库性能测试:sysbench用法详解

    1.简介和安装 sysbench是一个很不错的数据库性能测试工具. 官方站点:https://github.com/akopytov/sysbench/ rpm包下载:https://packagec ...

  5. μC/OS-II 任务堆栈的初始化

    任务堆栈的作用 应用程序在创建一个新任务的时候,必须把在系统启动这个任务时 CPU 各寄存器所需要的初始数据(任务指针.任务堆栈指针.程序状态字等等),事先存放在任务的堆栈中,以备任务切换等操作时调用 ...

  6. zabbix实现百台服务器的自动化监控--技术流ken

    前言 最近有小伙伴通过Q联系到我说:公司现在有百多台服务器,想要部署zabbix进行监控,怎么实现自动化全网监控? 本篇博客将讲解一个我工作时做的一个实际项目,现在写出来供大家以后参考使用. 实现自动 ...

  7. 多选穿梭框总结 (vue + element)

    博客地址:https://ainyi.com/23 示例 介绍 实现省市区三级多选联动,可任选一个省级.市级.区级,加入已选框,也可以在已选框中删除对应的区域. 选择对应仓库,自动勾选仓库对应的省,取 ...

  8. CoreJava(一)—— Java迭代语句

    本文介绍一些关于迭代语句的一些相关技巧以及Java8中的迭代语句的使用方法. public class TestBreak { public static void main(String[] arg ...

  9. [心得]如何快速利用SqlMap做安全檢測

    SqlMap的介紹我就不詳提啦!SqlMap是用來尋找與做Sql-injection的一款工具 在使用前你需要安裝python唷!安裝的過程我們就不介紹了. 直接來看如何快速使用SqlMap吧! 這裡 ...

  10. .net core部署在iis上

    部署在Windows Server 2008 R2上,一直安装失败,网上找的资料一直无法解决问题,后来找到了官方的文档, 原来是要安装sp1,大概2g左右,同时也要安装Microsoft Visual ...