zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    Java学习之集合(HashSet)
    Java学习之集合(LinkedList链表集合)
    Java学习之集合(List接口)
    Java学习之集合(Collection接口)
    【Spring Session】和 Redis 结合实现 Session 共享
    【NodeJS】nvm
    【Html JS】使用问题记录
    【VUE】使用问题记录
    【RabbitMQ】显示耗时处理进度
    【CentOS7】开发环境配置
  • 原文地址:https://www.cnblogs.com/wanbin/p/9514717.html
Copyright © 2011-2022 走看看