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 ...
随机推荐
- 洛谷 P3731 [HAOI2017]新型城市化【最大流(二分图匹配)+tarjan】
我到底怎么建的图为啥要开这么大的数组啊?! 神题神题,本来以为图论出不出什么花来了. 首先要理解'团'的概念,简单来说就是无向图的一个完全子图,相关概念详见度娘. 所以关于团一般都是NP问题,只有二分 ...
- poj 2398 Toy Storage【二分+叉积】
二分点所在区域,叉积判断左右 #include<iostream> #include<cstdio> #include<cstring> #include<a ...
- 洛谷 P3254 圆桌问题【最大流】
s向所有单位连流量为人数的边,所有饭桌向t连流量为饭桌容量的边,每个单位向每个饭桌连容量为1的边表示这个饭桌只能坐这个单位的一个人.跑dinic如果小于总人数则无解,否则对于每个单位for与它相连.满 ...
- thinkphp数据库查重方法
$test_data = M('hot'); //实例化数据表 $data = $test_data->Distinct(true)->field('descriprion')->o ...
- 全选Js
<th><input type="checkbox" value="" id="checkedAll" onclick=& ...
- 贪心/数学 Codeforces Round #212 (Div. 2) A. Two Semiknights Meet
题目传送门 /* 贪心/数学:还以为是BFS,其实x1 + 4 * k = x2, y1 + 4 * l = y2 */ #include <cstdio> #include <al ...
- JAVA Android王牌教程
Java基础 在Java基础系列文章中,我将说明Java的基础内容,特别是面向对象的相关概念. Java基础01 从HelloWorld到面向对象 Java基础02 方法与数据成员 Java基础03 ...
- ASP.NET URLRewriter重写
URLRewriter重写是微软官方出的第三方重写插件 下载地址:http://download.csdn.net/detail/ysn1314/5421587 下载后在项目中添加引用,然后再配置文件 ...
- 【RSA】在 ASP.NET Core中结合web前端JsEncrypt.JS使用公钥加密,.NET Core使用私钥解密;
有一个需求,前端web使用的是JsEncrypt把后端给的公钥对密码进行加密,然后后端对其进行解密: 使用的类库如下: 后端使用第三方开源类库Bouncy Castle进行RSA的加解密和生成PEM格 ...
- Java核心技术梳理-异常处理
一.引言 异常总是不可避免的,就算我们自身的代码足够优秀,但却不能保证用户都按照我们想法进行输入,就算用户按照我们的想法进行输入,我们也不能保证操作系统稳定,另外还有网络环境等,不可控因素太多,异常也 ...