SQL中带有NOT IN 子查询改写
报表程序中的一段SQL运行很慢,代码如下:
优化前:
耗时:1337s
INSERT INTO PER_LTE_ZIB_PB_COMMISSION_07
  SELECT P.TOPACTUALID,
         Q.POLICYNO,
         Q.ENDORSEMENTNO,
         CASE
           WHEN Q.ENDORSEMENTSTATUS = '$$900002107001' THEN
            '1'
           ELSE
            NULL
         END AS ENDORSE_CFLAG,
         P.ROLEID,
         P.OURFLAG,
         P.HOSTFLAG,
         P.AMOUNTOFPOLICYISSUINGFEES AS AMOUNTOFPOLICYISSUINGFEES,
         P.UWCODE,
         P.UWNAME,
         '04' AS DATATYPE,
         P.CURRENCYCODE,
         T3.TOPACTUALID AS NEXTTOPACTUALID,
         P.PAYEE,
         P.PAYEENAME
    FROM PER_LTE_ZIB_PB_COMMISSION_06 P
    LEFT JOIN (SELECT POLICYNO,
                      '0' AS ENDORSEMENTNO,
                      TOPACTUALID,
                      POLICYID,
                      NULL AS ENDORSEMENTSTATUS
                 FROM RPT_ST.POLICY
                WHERE POLICYNO IS NOT NULL
                  AND ENDORSEMENTID IS NULL
                  AND POLICYSTATUS IS NOT NULL
               UNION ALL
               SELECT T1.POLICYNO,
                      T2.ENDORSEMENTNO,
                      T1.TOPACTUALID,
                      POLICYID,
                      T2.ENDORSEMENTSTATUS
                 FROM RPT_ST.POLICY T1
                 LEFT JOIN RPT_ST.ENDORSEMENT T2
                   ON T1.ENDORSEMENTID = T2.ENDORSEMENTID
                WHERE T1.POLICYNO IS NOT NULL
                  AND T2.ENDORSEMENTNO IS NOT NULL
                  AND POLICYSTATUS IS NOT NULL
                  AND T2.ENDORSEMENTSTATUS <> '$$900002107001') Q
      ON P.TOPACTUALID = Q.TOPACTUALID
    LEFT JOIN (SELECT S.TOPACTUALID,
                      S.POLICYID,
                      S.POLICYSTATUS,
                      NULL AS PREPOLICYID
                 FROM RPT_ST.POLICY S
                WHERE POLICYNO IS NOT NULL
                  AND ENDORSEMENTID IS NULL
                  AND POLICYSTATUS IS NOT NULL
               UNION ALL
               SELECT T1.TOPACTUALID,
                      T1.POLICYID,
                      T1.POLICYSTATUS,
                      T2.PREPOLICYID
                 FROM RPT_ST.POLICY T1
                 LEFT JOIN RPT_ST.ENDORSEMENT T2
                   ON T1.ENDORSEMENTID = T2.ENDORSEMENTID
                WHERE T1.POLICYNO IS NOT NULL
                  AND T2.ENDORSEMENTNO IS NOT NULL
                  AND POLICYSTATUS IS NOT NULL
                  AND T2.ENDORSEMENTSTATUS <> '$$900002107001') T3
      ON Q.POLICYID = T3.PREPOLICYID
     AND T3.POLICYSTATUS IS NOT NULL
   WHERE P.TOPACTUALID IN
         (SELECT TOPACTUALID
            FROM PER_LTE_ZIB_PB_COMMISSION_06 P
           WHERE P.OURFLAG || NVL(P.HOSTFLAG, 0) = '$$1000090000011')
     AND P.ROLEID NOT IN
         (SELECT ROLEID
            FROM PER_LTE_ZIB_PB_COMMISSION_06 P
           WHERE P.OURFLAG || NVL(P.HOSTFLAG, 0) = '$$1000090000011')
     AND Q.POLICYNO IS NOT NULL
Plan hash value: 21661008
---------------------------------------------------------------------------------------------------------------------
| Id  | Operation            | Name                         | Rows  | Bytes | Cost (%CPU)| Time     | Inst   |IN-OUT|
---------------------------------------------------------------------------------------------------------------------
|   0 | INSERT STATEMENT     |                              |       |       |  9145 (100)|          |        |      |
|*  1 |  FILTER              |                              |       |       |            |          |        |      |
|*  2 |   HASH JOIN SEMI     |                              |     1 |   451 |  8782   (1)| 00:01:46 |        |      |
|*  3 |    HASH JOIN         |                              |     2 |   854 |  8418   (1)| 00:01:42 |        |      |
|*  4 |     HASH JOIN OUTER  |                              |     1 |   260 |  8056   (1)| 00:01:37 |        |      |
|   5 |      VIEW            |                              |     1 |   192 |  4028   (1)| 00:00:49 |        |      |
|   6 |       UNION-ALL      |                              |       |       |            |          |        |      |
|   7 |        REMOTE        | POLICY                       |     1 |   143 |  4028   (1)| 00:00:49 |  ENOLC | R->S |
|   8 |        REMOTE        |                              |       |       |            |          |  ENOLC | R->S |
|   9 |      VIEW            |                              |     1 |    68 |  4028   (1)| 00:00:49 |        |      |
|  10 |       UNION-ALL      |                              |       |       |            |          |        |      |
|  11 |        REMOTE        | POLICY                       |     1 |   130 |  4028   (1)| 00:00:49 |  ENOLC | R->S |
|  12 |        REMOTE        |                              |       |       |            |          |  ENOLC | R->S |
|  13 |     TABLE ACCESS FULL| PER_LTE_ZIB_PB_COMMISSION_06 | 65448 |    10M|   361   (1)| 00:00:05 |        |      |
|* 14 |    TABLE ACCESS FULL | PER_LTE_ZIB_PB_COMMISSION_06 |   654 | 15696 |   363   (2)| 00:00:05 |        |      |
|* 15 |   TABLE ACCESS FULL  | PER_LTE_ZIB_PB_COMMISSION_06 |     1 |    24 |   363   (2)| 00:00:05 |        |      |
---------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter( IS NULL)
   2 - access("P"."TOPACTUALID"="TOPACTUALID")
   3 - access("P"."TOPACTUALID"="Q"."TOPACTUALID")
   4 - access("Q"."POLICYID"="T3"."PREPOLICYID")
  14 - filter("P"."OURFLAG"||NVL("P"."HOSTFLAG",'0')='$$1000090000011')
  15 - filter(("P"."OURFLAG"||NVL("P"."HOSTFLAG",'0')='$$1000090000011' AND LNNVL("ROLEID"<>:B1)))分析
分析SQL代码,其中where 条件中有NOT IN(select roleid from per..)子查询。
去掉not in子查询,进行查询,能在3s内结果,由此该SQL性能瓶颈就出在NOT IN子查询上。
而NOT IN子查询,可以等价改写成left join,改写形式如下:
P.ROLEID NOT IN
         (SELECT ROLEID
            FROM PER_LTE_ZIB_PB_COMMISSION_06 P
           WHERE P.OURFLAG || NVL(P.HOSTFLAG, 0) = '$$1000090000011')
改写成:
LEFT JOIN (SELECT ROLEID
            FROM PER_LTE_ZIB_PB_COMMISSION_06 P
           WHERE P.OURFLAG || NVL(P.HOSTFLAG, 0) = '$$1000090000011') D
        ON D.ROLEID=P.ROLEID
 where  D.ROLEID IS NULL
整体改下SQL如下:
INSERT INTO PER_LTE_ZIB_PB_COMMISSION_07
  SELECT P.TOPACTUALID,
         Q.POLICYNO,
         Q.ENDORSEMENTNO,
         CASE
           WHEN Q.ENDORSEMENTSTATUS = '$$900002107001' THEN
            '1'
           ELSE
            NULL
         END AS ENDORSE_CFLAG,
         P.ROLEID,
         P.OURFLAG,
         P.HOSTFLAG,
         P.AMOUNTOFPOLICYISSUINGFEES AS AMOUNTOFPOLICYISSUINGFEES,
         P.UWCODE,
         P.UWNAME,
         '04' AS DATATYPE,
         P.CURRENCYCODE,
         T3.TOPACTUALID AS NEXTTOPACTUALID,
         P.PAYEE,
         P.PAYEENAME
    FROM PER_LTE_ZIB_PB_COMMISSION_06 P
    LEFT JOIN (SELECT POLICYNO,
                      '0' AS ENDORSEMENTNO,
                      TOPACTUALID,
                      POLICYID,
                      NULL AS ENDORSEMENTSTATUS
                 FROM RPT_ST.POLICY
                WHERE POLICYNO IS NOT NULL
                  AND ENDORSEMENTID IS NULL
                  AND POLICYSTATUS IS NOT NULL
               UNION ALL
               SELECT T1.POLICYNO,
                      T2.ENDORSEMENTNO,
                      T1.TOPACTUALID,
                      POLICYID,
                      T2.ENDORSEMENTSTATUS
                 FROM RPT_ST.POLICY T1
                 LEFT JOIN RPT_ST.ENDORSEMENT T2
                   ON T1.ENDORSEMENTID = T2.ENDORSEMENTID
                WHERE T1.POLICYNO IS NOT NULL
                  AND T2.ENDORSEMENTNO IS NOT NULL
                  AND POLICYSTATUS IS NOT NULL
                  AND T2.ENDORSEMENTSTATUS <> '$$900002107001') Q
      ON P.TOPACTUALID = Q.TOPACTUALID
    LEFT JOIN (SELECT S.TOPACTUALID,
                      S.POLICYID,
                      S.POLICYSTATUS,
                      NULL AS PREPOLICYID
                 FROM RPT_ST.POLICY S
                WHERE POLICYNO IS NOT NULL
                  AND ENDORSEMENTID IS NULL
                  AND POLICYSTATUS IS NOT NULL
               UNION ALL
               SELECT T1.TOPACTUALID,
                      T1.POLICYID,
                      T1.POLICYSTATUS,
                      T2.PREPOLICYID
                 FROM RPT_ST.POLICY T1
                 LEFT JOIN RPT_ST.ENDORSEMENT T2
                   ON T1.ENDORSEMENTID = T2.ENDORSEMENTID
                WHERE T1.POLICYNO IS NOT NULL
                  AND T2.ENDORSEMENTNO IS NOT NULL
                  AND POLICYSTATUS IS NOT NULL
                  AND T2.ENDORSEMENTSTATUS <> '$$900002107001') T3
      ON Q.POLICYID = T3.PREPOLICYID
     AND T3.POLICYSTATUS IS NOT NULL
   LEFT JOIN (SELECT ROLEID
            FROM PER_LTE_ZIB_PB_COMMISSION_06 P
           WHERE P.OURFLAG || NVL(P.HOSTFLAG, 0) = '$$1000090000011') D
        ON D.ROLEID=P.ROLEID
   WHERE P.TOPACTUALID IN
         (SELECT TOPACTUALID
            FROM PER_LTE_ZIB_PB_COMMISSION_06 P
           WHERE P.OURFLAG || NVL(P.HOSTFLAG, 0) = '$$1000090000011')
                AND Q.POLICYNO IS NOT NULL
                AND D.ROLEID IS NULL
----------------------------------------------------------------------------------------------------------------------
| Id  | Operation             | Name                         | Rows  | Bytes | Cost (%CPU)| Time     | Inst   |IN-OUT|
----------------------------------------------------------------------------------------------------------------------
|   0 | INSERT STATEMENT      |                              |     1 |   475 |  9145   (1)| 00:01:50 |        |      |
|*  1 |  HASH JOIN SEMI       |                              |     1 |   475 |  9145   (1)| 00:01:50 |        |      |
|*  2 |   FILTER              |                              |       |       |            |          |        |      |
|*  3 |    HASH JOIN OUTER    |                              |     1 |   451 |  8781   (1)| 00:01:46 |        |      |
|*  4 |     HASH JOIN         |                              |     2 |   854 |  8418   (1)| 00:01:42 |        |      |
|*  5 |      HASH JOIN OUTER  |                              |     1 |   260 |  8056   (1)| 00:01:37 |        |      |
|   6 |       VIEW            |                              |     1 |   192 |  4028   (1)| 00:00:49 |        |      |
|   7 |        UNION-ALL      |                              |       |       |            |          |        |      |
|   8 |         REMOTE        | POLICY                       |     1 |   143 |  4028   (1)| 00:00:49 |  ENOLC | R->S |
|   9 |         REMOTE        |                              |       |       |            |          |  ENOLC | R->S |
|  10 |       VIEW            |                              |     1 |    68 |  4028   (1)| 00:00:49 |        |      |
|  11 |        UNION-ALL      |                              |       |       |            |          |        |      |
|  12 |         REMOTE        | POLICY                       |     1 |   130 |  4028   (1)| 00:00:49 |  ENOLC | R->S |
|  13 |         REMOTE        |                              |       |       |            |          |  ENOLC | R->S |
|  14 |      TABLE ACCESS FULL| PER_LTE_ZIB_PB_COMMISSION_06 | 65448 |    10M|   361   (1)| 00:00:05 |        |      |
|* 15 |     TABLE ACCESS FULL | PER_LTE_ZIB_PB_COMMISSION_06 |   654 | 15696 |   363   (2)| 00:00:05 |        |      |
|* 16 |   TABLE ACCESS FULL   | PER_LTE_ZIB_PB_COMMISSION_06 |   654 | 15696 |   363   (2)| 00:00:05 |        |      |
----------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - access("P"."TOPACTUALID"="TOPACTUALID")
   2 - filter("ROLEID" IS NULL)
   3 - access("ROLEID"(+)="P"."ROLEID")
   4 - access("P"."TOPACTUALID"="Q"."TOPACTUALID")
   5 - access("Q"."POLICYID"="T3"."PREPOLICYID"(+))
  15 - filter("P"."OURFLAG"(+)||NVL("P"."HOSTFLAG"(+),'0')='$$1000090000011')
  16 - filter("P"."OURFLAG"||NVL("P"."HOSTFLAG",'0')='$$1000090000011')
Remote SQL Information (identified by operation id):
----------------------------------------------------
   8 - SELECT "POLICYID","POLICYNO","POLICYSTATUS","TOPACTUALID","ENDORSEMENTID" FROM "CUAN_DOIC"."POLICY"
       "POLICY" WHERE "ENDORSEMENTID" IS NULL AND "POLICYNO" IS NOT NULL AND "POLICYSTATUS" IS NOT NULL (accessing
       'ENOLC' )
   9 - EXPLAIN PLAN INTO PLAN_TABLE@! FOR SELECT "A2"."POLICYNO","A1"."ENDORSEMENTNO","A2"."TOPACTUALID","A2".
       "POLICYID","A1"."ENDORSEMENTSTATUS" FROM "CUAN_DOIC"."POLICY" "A2","CUAN_DOIC"."ENDORSEMENT" "A1" WHERE
       "A2"."POLICYNO" IS NOT NULL AND "A1"."ENDORSEMENTNO" IS NOT NULL AND "A2"."POLICYSTATUS" IS NOT NULL AND
       "A1"."ENDORSEMENTSTATUS"<>'$$900002107001' AND "A2"."ENDORSEMENTID"="A1"."ENDORSEMENTID" AND "A2"."POLICYNO"
       IS NOT NULL (accessing 'ENOLC' )
  12 - SELECT "POLICYNO","POLICYSTATUS","TOPACTUALID","ENDORSEMENTID" FROM "CUAN_DOIC"."POLICY" "S" WHERE
        "ENDORSEMENTID" IS NULL AND "POLICYNO" IS NOT NULL AND "POLICYSTATUS" IS NOT NULL (accessing 'ENOLC' )
  13 - EXPLAIN PLAN INTO PLAN_TABLE@! FOR SELECT "A2"."TOPACTUALID","A2"."POLICYID","A2"."POLICYSTATUS","A1"."
        PREPOLICYID" FROM "CUAN_DOIC"."POLICY" "A2","CUAN_DOIC"."ENDORSEMENT" "A1" WHERE "A2"."POLICYNO" IS NOT NULL
        AND "A1"."ENDORSEMENTNO" IS NOT NULL AND "A2"."POLICYSTATUS" IS NOT NULL AND
        "A1"."ENDORSEMENTSTATUS"<>'$$900002107001' AND "A2"."ENDORSEMENTID"="A1"."ENDORSEMENTID" AND
        "A2"."POLICYSTATUS" IS NOT NULL (accessing 'ENOLC' )                           优化后
耗时:4s
SQL中带有NOT IN 子查询改写的更多相关文章
- SQL Server中INNER JOIN与子查询IN的性能测试
		这个月碰到几个人问我关于"SQL SERVER中INNER JOIN 与 IN两种写法的性能孰优孰劣?"这个问题.其实这个概括起来就是SQL Server中INNER JOIN与子 ... 
- 你真的会玩SQL吗?无处不在的子查询
		你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ... 
- SQL点滴10—使用with语句来写一个稍微复杂sql语句,附加和子查询的性能对比
		原文:SQL点滴10-使用with语句来写一个稍微复杂sql语句,附加和子查询的性能对比 今天偶尔看到sql中也有with关键字,好歹也写了几年的sql语句,居然第一次接触,无知啊.看了一位博主的文章 ... 
- SQL系列(九)—— 子查询(subQuery)
		1.子查询 前面的系列介绍的都是简单的查询场景,其中都只涉及到单张表的数据检索.但是在日常是实际应用中,数据模型之间的关系都非常的复杂,数据的需求一般都是来源于多个数据模型之间的组合而成,即对应多张表 ... 
- Mysql常用sql语句(20)- 子查询重点知识
		测试必备的Mysql常用sql语句系列 https://www.cnblogs.com/poloyy/category/1683347.html 子查询语句可以嵌套在 sql 语句中任何表达式出现的位 ... 
- paip.sql索引优化----join 代替子查询法
		paip.sql索引优化----join 代替子查询法 作者Attilax , EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http://blog.csdn.n ... 
- 走向面试之数据库基础:二、SQL进阶之case、子查询、分页、join与视图
		一.CASE的两种用法 1.1 等值判断->相当于switch case (1)具体用法模板: CASE expression WHEN value1 THEN returnvalue1 WHE ... 
- SQL主外键和子查询
		主键 数据库主键是指表中一个列或列的组合,其值能唯一地标识表中的每一行.这样的一列或多列称为表的主键,通过它可强制表的实体完整性.当创建或更改表时可通过定义 PRIMARY KEY约束来创建主键.一个 ... 
- SQL笔记-第八章,子查询
		一.SELECT列表中的标量子查询 查询每种书籍类型中的最早出版的书籍.在SQL 查询中,需要将一本书籍的出版年份与该类型的所有书籍的出版年份进行比较,并且仅仅在它们匹配时,才返回一个记录 SELEC ... 
随机推荐
- CentOS7.5 -- Ansible部署与应用
			第1章 Ansible概述 Ansible是一个配置管理系统configuration management system python 语言是运维人员必须会的语言 ansible 是一个基于pyth ... 
- 4 Java 如何判定是否存活或者死亡
			在堆中存放着几乎所有的对象实例,垃圾收集器在对堆进行回收前,第一件事就是要确定这些对象之中哪些还活着,哪些对象已经死去. 判断对象是否已经死亡有以下几种算法: 引用计数法算法 定义 : 给对象中添加一 ... 
- pytest特色与实用插件
			pytest特色 1.fixture的特点 fixture是pytest特有的功能,其特点如下: 必须用pytest.fixture装饰器装饰:fixture有明确的名字,在其他函数(function ... 
- python常用的装饰器
			一.为程序添加时间类的装饰器二.验证用户是否等陆 #.为函数添加统计时间的装饰器: import time def timeer(func): def inner(): starttime=time. ... 
- Hdu 5384 Danganronpa (AC自动机模板)
			题目链接: Hdu 5384 Danganronpa 题目描述: 给出n个目标串Ai,m个模式串Bj,问每个目标串中m个模式串出现的次数总和为多少? 解题思路: 与Hdu 2222 Keywords ... 
- 题解报告:hdu 2086 A1 = ?
			题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2086 Problem Description 有如下方程:Ai = (Ai-1 + Ai+1)/2 - ... 
- 452 Minimum Number of Arrows to Burst Balloons 用最少数量的箭引爆气球
			在二维空间中有许多球形的气球.对于每个气球,提供的输入是水平方向上,气球直径的开始和结束坐标.由于它是水平的,所以y坐标并不重要,因此只要知道开始和结束的x坐标就足够了.开始坐标总是小于结束坐标.平面 ... 
- UWP Windows10开发获取设备位置(经纬度)
			1.首先要在UWP项目的Package.appxmanifest文件中配置位置权限,如下图所示: 2.Package.appxmanifest后选择第三个选项卡,勾选位置权限(Location) 打开 ... 
- GIT配置及用法
			ssh配置 TortoiseGit配置 用法: 下面是我整理的常用 Git 命令清单.几个专用名词的译名如下. Workspace:工作区 Index / Stage:暂存区 Repository:仓 ... 
- 详解Android Activity启动模式
			相关的基本概念: 1.任务栈(Task) 若干个Activity的集合的栈表示一个Task. 栈不仅仅只包含自身程序的Activity,它也可以跨应用包含其他应用的Activity,这样有利于 ... 
