merge into sql优化
今天网友说他的merge into sql跑了15分钟了还没有跑出数据,问我能不能优化一下,我让他把sql和sql的执行计划发过来
merge into F_Sal_P_Camp_Samp_Cust_Data A
using (select CUST_ID,
CUST_MNGR_ID,
ORGCODE From (
SELECT t.CUST_ID,
t.CUST_MNGR_ID,
t.ORGCODE,
ROW_NUMBER() OVER(PARTITION BY t.cust_id ORDER BY t.BELG_RELA_TYPE asc,t.open_percent DESC) AS RN
From F_Sal_P_Camp_Samp_Cust_Data a
INNER JOIN (
SELECT T.CUST_ID,T.CUST_MNGR_ID,T.BELG_RELA_TYPE,T.OPEN_PERCENT,OM.ORGSEQ,OM.ORGCODE
FROM O_F_PTY_P_CUST_BELG_INFO T
INNER JOIN OM_EMPLOYEE EMP
ON t.CUST_MNGR_ID = EMP.EMPCODE
and emp.empname not like '%虚拟%'
INNER JOIN AC_OPERATOR opr
ON emp.operatorid = opr.operatorid
AND opr.status IN ('running', 'openuse')
INNER JOIN OM_ORGANIZATION OM
ON EMP.ORGADMINID = OM.ORGID
) t ON A.CUST_ID=T.CUST_ID
where A.activity_id = '20150114-1003' AND t.orgseq like '.10001.'||'%'
and A.used_org = 'BS001'
and A.execute_man is null
) where rn = 1
) t1
on (A.CUST_ID = T1.cust_id AND A.activity_id = '20150114-1003')
when matched then
update
set A.execute_man = T1.CUST_MNGR_ID,
A.task_stat = '3',
a.Used_Org = T1.ORGCODE
WHERE A.activity_id = '20150114-1003'

5 - filter("RN"=1)
6 - filter(ROW_NUMBER() OVER ( PARTITION BY "T"."CUST_ID" ORDER BY
"T"."BELG_RELA_TYPE",INTERNAL_FUNCTION("T"."OPEN_PERCENT") DESC )<=1)
12 - filter("A"."USED_ORG"='BS001' AND "A"."EXECUTE_MAN" IS NULL)
13 - access("A"."ACTIVITY_ID"='20150114-1003')
15 - access("A"."CUST_ID"="T"."CUST_ID")
16 - filter("EMP"."EMPNAME" NOT LIKE '%虚拟%' AND "EMP"."EMPNAME" IS NOT NULL)
17 - access("T"."CUST_MNGR_ID"="EMP"."EMPCODE")
18 - filter("OPR"."STATUS"='openuse' OR "OPR"."STATUS"='running')
19 - access("EMP"."OPERATORID"="OPR"."OPERATORID")
20 - access("EMP"."ORGADMINID"="OM"."ORGID")
21 - filter("OM"."ORGSEQ" LIKE '.10001.%')
22 - access("A"."ACTIVITY_ID"='20150114-1003')
23 - filter("A"."CUST_ID"="CUST_ID")
看了这个执行计划,发现全都是NL连接,我让他查询相应sql返回的行数
F_Sal_P_Camp_Samp_Cust_Data 返回20w
select count(*) from O_F_PTY_P_CUST_BELG_INFO T; 369983
select count(*) from OM_EMPLOYEE EMP where emp.empname not like '%虚拟%; 6353
select count(*) from AC_OPERATOR opr where opr.status IN ('running', 'openuse'); 3234
select count(*) from OM_ORGANIZATION OM; 1079
发现返回的行数都不少,走NL连接一定有问题,应该走hash join,而且执行计划上看统计信息也是不对的
由于网友是开发没有dba权限,所以不能 重新统计信息,所以只能使用hint,添加了hint强制走hash,运行时间是19秒,网友说可以了,我在帮他看看
merge /*+ use_hash(A,t1) leading(A) */ into F_Sal_P_Camp_Samp_Cust_Data A
using (select CUST_ID,
CUST_MNGR_ID,
ORGCODE From (
SELECT /*+ use_hash(A,t) leading(a) */t.CUST_ID,
t.CUST_MNGR_ID,
t.ORGCODE,
ROW_NUMBER() OVER(PARTITION BY t.cust_id ORDER BY t.BELG_RELA_TYPE asc,t.open_percent DESC) AS RN
From F_Sal_P_Camp_Samp_Cust_Data a
INNER JOIN (
SELECT T.CUST_ID,T.CUST_MNGR_ID,T.BELG_RELA_TYPE,T.OPEN_PERCENT,OM.ORGSEQ,OM.ORGCODE
FROM O_F_PTY_P_CUST_BELG_INFO T
INNER JOIN OM_EMPLOYEE EMP
ON t.CUST_MNGR_ID = EMP.EMPCODE
and emp.empname not like '%虚拟%'
INNER JOIN AC_OPERATOR opr
ON emp.operatorid = opr.operatorid
AND opr.status IN ('running', 'openuse')
INNER JOIN OM_ORGANIZATION OM
ON EMP.ORGADMINID = OM.ORGID
) t ON A.CUST_ID=T.CUST_ID
where A.activity_id = '20150114-1003' AND t.orgseq like '.10001.'||'%'
and A.used_org = 'BS001'
and A.execute_man is null
) where rn = 1
) t1
on (A.CUST_ID = T1.cust_id AND A.activity_id = '20150114-1003')
when matched then
update
set A.execute_man = T1.CUST_MNGR_ID,
A.task_stat = '3',
a.Used_Org = T1.ORGCODE
WHERE A.activity_id = '20150114-1003'
这个sql中间嵌套了很多层,这是中间那层,这个sql跑了2:30秒
SELECT T.CUST_ID,T.CUST_MNGR_ID,T.BELG_RELA_TYPE,T.OPEN_PERCENT,OM.ORGSEQ,OM.ORGCODE
FROM O_F_PTY_P_CUST_BELG_INFO T
INNER JOIN OM_EMPLOYEE EMP
ON t.CUST_MNGR_ID = EMP.EMPCODE
and emp.empname not like '%虚拟%'
INNER JOIN AC_OPERATOR opr
ON emp.operatorid = opr.operatorid
AND opr.status IN ('running', 'openuse')
INNER JOIN OM_ORGANIZATION OM
ON EMP.ORGADMINID = OM.ORGID

select count(*) from O_F_PTY_P_CUST_BELG_INFO T; 369983
select count(*) from OM_EMPLOYEE EMP where emp.empname not like '%虚拟%; 6353
select count(*) from AC_OPERATOR opr where opr.status IN ('running', 'openuse'); 3234
select count(*) from OM_ORGANIZATION OM; 1079
看了这个执行计划,看了sql返回的行数,发现非常好,走的hash连接是对的,那为什么走的慢呢,因为所有的表走的都是全表扫描,没有走索引,但是能走索引的都是小表,没有影响,
真正有影响的是T表,T表30多w,而且没有筛选条件,只能改写sql了
with X as ( select /*+ materialize parallel(T,6) */ T.CUST_ID,T.CUST_MNGR_ID,T.BELG_RELA_TYPE,T.OPEN_PERCENT from O_F_PTY_P_CUST_BELG_INFO T)
SELECT X.CUST_ID,X.CUST_MNGR_ID,X.BELG_RELA_TYPE,X.OPEN_PERCENT,OM.ORGSEQ,OM.ORGCODE
FROM X
INNER JOIN OM_EMPLOYEE EMP
ON X.CUST_MNGR_ID = EMP.EMPCODE
and emp.empname not like '%虚拟%'
INNER JOIN AC_OPERATOR opr
ON emp.operatorid = opr.operatorid
AND opr.status IN ('running', 'openuse')
INNER JOIN OM_ORGANIZATION OM
ON EMP.ORGADMINID = OM.ORGID

sql改写之后跑了1分钟,快了好多
整个sql跑起来,在10秒左右,改到这里就可以了
本人qq 343548233,期待和各位交流,一起探讨sql,提高sql性能
merge into sql优化的更多相关文章
- ORACLE常用SQL优化hint语句
在SQL语句优化过程中,我们经常会用到hint,现总结一下在SQL优化过程中常见Oracle HINT的用法: 1. /*+ALL_ROWS*/ 表明对语句块选择基于开销的优化方法,并获得最佳吞吐量, ...
- 基于Oracle的SQL优化(社区万众期待 数据库优化扛鼎巨著)
基于Oracle的SQL优化(社区万众期待数据库优化扛鼎巨著) 崔华 编 ISBN 978-7-121-21758-6 2014年1月出版 定价:128.00元 856页 16开 编辑推荐 本土O ...
- Oracle SQL优化一(常见方法)
1.表访问方式优化: a)普通表优先“Index Lookup 索引扫描”,避免全表扫描 大多数场景下,通过“Index Lookup 索引扫描”要比“Full Table Scan (FTS) 全表 ...
- sql优化点整理
此文是我最早开始sql优化至今整理的小知识点和经常遇到的问题,弄懂这些对优化大型的sql会有不少帮助 ---------------------------------使用了多余的外连接------- ...
- 大型系统开发sql优化总结(转)
Problem Description: 1.每个表的结构及主键索引情况 2.每个表的count(*)记录是多少 3.对于创建索引的列,索引的类型是什么?count(distinct indexcol ...
- Oracle 表三种连接方式(sql优化)
在查看sql执行计划时,我们会发现表的连接方式有多种,本文对表的连接方式进行介绍以便更好看懂执行计划和理解sql执行原理. 一.连接方式: 嵌套循环(Nested Loops (NL)) (散列)哈希 ...
- sql优化--in和exists效率
系统要求进行SQL优化,对效率比较低的SQL进行优化,使其运行效率更高,其中要求对SQL中的部分in/not in修改为exists/not exists 修改方法如下: in的SQL语句 SELEC ...
- Oracle SQL优化[转]
Oracle SQL优化 1. 选用适合的ORACLE优化器 ORACLE的优化器共有3种: a. RULE (基于规则) b. COST (基于成本) c. CHOOSE (选择性) 设置缺省的优化 ...
- 基于oracle的sql优化
[基于oracle的sql优化] 基于oracle的sql优化 [博主]高瑞林 [博客地址]http://www.cnblogs.com/grl214 一.编写初衷描述 在应有系统开发初期,由于数据库 ...
随机推荐
- Android-AttributeSet详解
public interface AttributeSet { /** * Returns the number of attributes available in the set. * * @re ...
- Inventory > INV.MTL_MATERIAL_TRANSACTIONS Show Error Msg: ORA-20100: File lxxx.tmp creation for FND_FILE failed.
Fixed Step. 1. Backup error data CREATE TABLE MMT_BACKUP_0805 AS SELECT * FROM INV.MTL_MATERIAL_T ...
- Linux kernel ‘aac_send_raw_srb’函数输入验证漏洞
漏洞名称: Linux kernel ‘aac_send_raw_srb’函数输入验证漏洞 CNNVD编号: CNNVD-201311-422 发布时间: 2013-11-29 更新时间: 2013- ...
- 深入理解c语言_从编译器的角度考虑问题_纪念Dennis Ritchie先生
开源中国: Dennis Ritchie教授过世了,他发明了C语言,一个影响深远并彻底改变世界的计算机语言.一门经历40多年的到今天还长盛不训的语言,今天很多语言都受到C的影 响,C++,Java,C ...
- 【转】我的WIN7分辨率是1920*1080,调低后字体模糊
原文网址:http://tieba.baidu.com/p/778306758 WIN7还有一个“使用XP风格DPI缩放”的选项,如果选中则只放大文字,不选会连对话框和文字全部放大 这么多层楼,只有这 ...
- 用css控制cellspacing、cellpadding
用css控制cellspacing.cellpadding 发表于 2006 年 12 月 24 日 由 Silbo 在table中控制单元格之间的间距要用到cellspacing.cellpaddi ...
- RegisterFunction z
#region SolidWorks Registration [ComRegisterFunctionAttribute] public static void RegisterFunction(T ...
- Python能做什么
There should be one--and preferably only one --obvious way to do it. 首先,对于小白来说,Python比较容易上手.额就是个活 ...
- dev/null和dev/zero区别 以及换回设备(loopback device)
转自:http://blog.chinaunix.net/uid-20729677-id-765105.html dev/zero,是一个输入设备,你可你用它来初始化文件. /dev/zero---- ...
- https://lua-toolbox.com/
Lua Toolbox https://github.com/bungle/lua-resty-session