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 ...
随机推荐
- UVa 12717 Fiasco (BFS模拟)
题意:给定一个错误代码,让你修改数据,使得它能够输出正确答案,错误代码是每次取最短的放入. 析:那么我们就可以模拟这个过程,然后修改每条边的权值,使得它能输出正确答案. 代码如下: #pragma c ...
- 【黑金教程笔记之007】【建模篇】【Lab 06 SOS信号之二】—笔记
控制模块的协调角色. 实验六用到了实验四的按键消抖模块debounce_module.v和实验五的sos_module.v. 设计思路: debounce_module.v看成一个输入,sos_mod ...
- 通过实现ServletContextListener接口创建数据库连接池(C3P0方式)
使用Listener步骤 1. 定义Listener实现类 2. 在web.xml中配置(或使用Annotation) 使用C3P0方式创建数据库连接池需要添加的jar包 1.c3p0-0.9.5.j ...
- div拖拽互换位置(vue)
template模板 <transition-group tag="div" class="container"> <div class=&q ...
- bzoj 2216: [Poi2011]Lightning Conductor【决策单调性dp+分治】
参考:https://blog.csdn.net/clove_unique/article/details/57405845 死活不过样例看了题解才发现要用double.... \[ a_j \leq ...
- P5089 [eJOI2018]元素周期表(并查集)
传送门 以后看到棋盘要么黑白染色要么二分图! 我们考虑对行列建二分图,如果\(i\)行\(j\)列有,就把\(i\)和\(j+n\)连起来 我们要让它变成一张完全二分图.考虑条件\((i_1,j_1+ ...
- 【css】如何实现环形进度条
最近团队的童鞋接到了一个有关环形进度条的需求,想要还原一个native的沿环轨迹渐变进度条的效果,看到这个效果的时候,笔者陷入了沉思.. 环形进度条的效果,最先想到的就是使用CSS利用两个半圆的hac ...
- ACM配置指南
Ubuntu桌面入门指南 ACM比赛系统ubuntu 使用指南 ACM核武器 简明 Vim 练级攻略 Vim命令合集 代码编辑神器VIM(附我写acm程序时的配置) my_vimrc in ubunt ...
- C. Timofey and a tree 观察题 + dfs模拟
http://codeforces.com/contest/764/problem/C 题意:在n个顶点中随便删除一个,然后分成若干个连通子图,要求这若干个连通子图的颜色都只有一种. 记得边是双向的, ...
- poj1715Hexadecimal Numbers(数位dp)
链接 好久没写这种逐位计数的了. 先统计出总的数 ,s-n+1,倒着计算的 ,感觉倒着比较符合计算方式,总数为15*A(15,i) (1=<i<=8) 也就是1-8长度所有的排列总数 然后 ...