SQL中带有NOT IN 子查询改写
2017-12-04 14:10
330 查看
报表程序中的一段SQL运行很慢,代码如下:
耗时:1337s
整体改下SQL如下:
耗时:4s
优化前:
耗时: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中的联表查询(NOT IN与IS NULL)
- 将textarea/Input里面带有‘换行符’或者空格的字符串处理成用','分隔的支持SQL的in()查询
- MS SQL Server带有时间的记录怎样查询
- Sql语句优化-查询两表不同行NOT IN、NOT EXISTS、连接查询Left Join
- SQL提高查询效益之in、not in、between、like等条件讲述
- SQL查询——NOT IN与NOT EXIST的区别
- TP 查询时候标题带有&的字符,查询没有结果!打出SQL语句去数据库查,返回有结果!
- SQL查询性能分析之(not in)、(and not)、(<>)、(!=)性能比较
- sql查询优化(一),not in及详细讲解提高数据库查询效率
- sql 在not in 子查询有null值情况下经常出现的陷阱
- Java 实现SparkSQL保存查询结果带有字段信息到(header)HDFS
- 标量子查询SQL改写一则(包括WITH的改写)
- SQL查询性能优化 之 LEFT JOIN 替换 NOT IN
- sql: not in和联接(left join)查询的比较
- sql的一个查询,情景:a表中存在的数据,且在b表中不存在 (not in,not exists
- SQL提高查询效益之in、not in、between、like等条件讲述
- SQL 中 NOT IN 查询不到数据
- sql 在not in 子查询有null值情况下经常出现的陷阱
- SQL 查询中not in 与 not exists 的区别