今天网友说他的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优化的更多相关文章

  1. ORACLE常用SQL优化hint语句

    在SQL语句优化过程中,我们经常会用到hint,现总结一下在SQL优化过程中常见Oracle HINT的用法: 1. /*+ALL_ROWS*/ 表明对语句块选择基于开销的优化方法,并获得最佳吞吐量, ...

  2. 基于Oracle的SQL优化(社区万众期待 数据库优化扛鼎巨著)

    基于Oracle的SQL优化(社区万众期待数据库优化扛鼎巨著) 崔华 编   ISBN 978-7-121-21758-6 2014年1月出版 定价:128.00元 856页 16开 编辑推荐 本土O ...

  3. Oracle SQL优化一(常见方法)

    1.表访问方式优化: a)普通表优先“Index Lookup 索引扫描”,避免全表扫描 大多数场景下,通过“Index Lookup 索引扫描”要比“Full Table Scan (FTS) 全表 ...

  4. sql优化点整理

    此文是我最早开始sql优化至今整理的小知识点和经常遇到的问题,弄懂这些对优化大型的sql会有不少帮助 ---------------------------------使用了多余的外连接------- ...

  5. 大型系统开发sql优化总结(转)

    Problem Description: 1.每个表的结构及主键索引情况 2.每个表的count(*)记录是多少 3.对于创建索引的列,索引的类型是什么?count(distinct indexcol ...

  6. Oracle 表三种连接方式(sql优化)

    在查看sql执行计划时,我们会发现表的连接方式有多种,本文对表的连接方式进行介绍以便更好看懂执行计划和理解sql执行原理. 一.连接方式: 嵌套循环(Nested Loops (NL)) (散列)哈希 ...

  7. sql优化--in和exists效率

    系统要求进行SQL优化,对效率比较低的SQL进行优化,使其运行效率更高,其中要求对SQL中的部分in/not in修改为exists/not exists 修改方法如下: in的SQL语句 SELEC ...

  8. Oracle SQL优化[转]

    Oracle SQL优化 1. 选用适合的ORACLE优化器 ORACLE的优化器共有3种: a. RULE (基于规则) b. COST (基于成本) c. CHOOSE (选择性) 设置缺省的优化 ...

  9. 基于oracle的sql优化

    [基于oracle的sql优化] 基于oracle的sql优化 [博主]高瑞林 [博客地址]http://www.cnblogs.com/grl214 一.编写初衷描述 在应有系统开发初期,由于数据库 ...

随机推荐

  1. poj2229Sumsets

    http://poj.org/problem?id=2229 挺好的一公式.. #include <iostream> #include<cstdio> #include< ...

  2. BZOJ_[HNOI2008]_Cards_(置换+Burnside引理+乘法逆元+费马小定理+快速幂)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1004 共n个卡片,染成r,b,g三种颜色,每种颜色的个数有规定.给出一些置换,可以由置换得到的 ...

  3. zabbix中文配置指南(转)-服务器监控

    一.Zabbix简介 1.1 Zabbix简介 Zabbix是一个企业级的开源分布式监控解决方案,由一个国外的团队持续维护更新,软件可以自由下载使用,运作团队靠提供收费的技术支持赢利.官方网站:htt ...

  4. 用Oracle的TRIM函数去除字符串首尾指定字符

    去掉首尾空格 SELECT TRIM(' abc '), ltrim(' abc '), rtrim(' abc ') FROM dual; 去掉首尾的其他字符 SELECT /*TRIM(';a;b ...

  5. [转]ASP.NET MVC 入门5、View与ViewData

    view在MVC模式中与用户进行最直接的接触,它负责数据的呈现.这里要注意一点就是,view只是负责数据的呈现,所以我们应该要尽量让view中不涉及业务逻辑的处理. 我们来添加一个Blog首页的vie ...

  6. [Raobin] Ext.net在前端直接将对象转为json形式传入后台

    d.Render.ExtraParams.Add(Html.Y().Parameter("Json", new JavaScriptSerializer().Serialize(e ...

  7. 【转+心得】WinDbg+VM9双机调试无法连接解决方案

    参考:http://www.52pojie.cn/forum.php?mod=viewthread&tid=203339 启动顺序为:先启动vmware里面的xp后(登录到桌面),再启动win ...

  8. [TYVJ1827]『Citric II』一道防AK好题

    时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 第二届『Citric杯』NOIP提高组模拟赛第一题 描述 Lemon认为在第一届『Citric』杯模拟赛中出的 ...

  9. linux 小技巧总结

    (1)linux判断文件是否存在 if [ -f filename]: then       ......#要执行的语句 fi 具体例子: file=/usr/local/oracle/oradata ...

  10. 合并多行查询数据到一行:使用自连接、FOR XML PATH('')、STUFF或REPLACE函数 (转)

    转自: http://www.cnblogs.com/aolin/archive/2011/04/12/2014122.html 示例表 tb 数据如下 id value—————1 aa1 bb2 ...