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 INselect 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

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值