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 ...
随机推荐
- VS2013程序打包报 ISEXP : error -****: An error occurred streaming
原因缺少打包文件 解决方案: 找到打包文件 右击选择 downLoad selected item
- Luogu P1991 无线通讯网 【最小生成树】
题目描述 国防部计划用无线网络连接若干个边防哨所.2 种不同的通讯技术用来搭建无线网络: 每个边防哨所都要配备无线电收发器:有一些哨所还可以增配卫星电话. 任意两个配备了一条卫星电话线路的哨所(两边都 ...
- jenkins软件工具部署
Jenkins服务软件的安装部署 1.我们在linux安装部署Jenkins的时候,因为jenkins是一个java web程序,所以首先要保证linux系统上已经安装配置好java JDK环境,并安 ...
- [ZPG TEST 105] 扑克游戏【Huffman】
扑克游戏 (poker) 题目描述: 有一棵无穷大的满二叉树,根为star,其余所有点的权值为点到根的距离,如图: 现在你有一些扑克牌,点数从1到13,你要把这些扑克牌全部放到这个树上: 当你把点数为 ...
- 逆序数 UVALive 6508 Permutation Graphs
题目传送门 /* 题意:给了两行的数字,相同的数字连线,问中间交点的个数 逆序数:第一行保存每个数字的位置,第二行保存该数字在第一行的位置,接下来就是对它求逆序数 用归并排序或线段树求.想到了就简单了 ...
- 首先定义一个5X8的二维数组,然后使用随机数填充满。借助Arrays的方法对二维数组进行排序。
package day02; import java.util.Arrays; import java.util.Random; public class Test01 { public static ...
- Linux的proc文件系统 分类: linux 2014-06-02 10:21 623人阅读 评论(0) 收藏
proc为一个内核数据结构接口,用户空间和内核空间可以通过该接口通信, 与普通文件不同的是,这些虚拟文件的内容都是动态创建的. proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间. ...
- java数组实现红包的方法
package Hongbao; import java.text.DecimalFormat; import java.util.Scanner; public class Hongbao { pu ...
- jQuery委托
$('#container').on('click', '.elementClass', function() { // code }); http://stackoverflow.com/quest ...
- math数学函数
Console.WriteLine("Math.Sign(12)--->{0})", Math.Sign(12)) Console.WriteLine("math. ...