您的位置:首页 > 数据库

SQL中带有NOT IN 子查询改写

2017-12-04 14:10 330 查看
报表程序中的一段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

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: