今天网友说他的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. IOS开发中单例模式使用详解

    第一.基本概念 单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例类的特殊类.通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问. 第二.在IOS中使用单例模式的情 ...

  2. linux多线程驱动中调用udelay()对整个系统造成的影响(by liukun321咕唧咕唧)

    以前没考虑过这个问题,而且之前可能运气比较好,虽然用了udelay但也没出什么奇怪的问题,今天在 CSDN上看到了一篇关于此问题帖子,觉得很受用,再此做简要的记录和分析: 驱动开的是内核线程 跟普通进 ...

  3. Sublime Text各种插件使用方法

    有快捷键冲突的时候可以修改快捷键,建议修改插件快捷键而不是Sublime Text的快捷键,我的有冲突的一律将插件快捷键设置成:Ctrl+Alt+A(B...) Package Control 通俗易 ...

  4. hdu4499Cannon(搜索)

    链接 这样的叫迭代吗..最近多做些搜索题了要 分行分列搜 判断满足条件 #include <iostream> #include<cstdio> #include<cst ...

  5. VJ1061迎春舞会之三人组舞

    题目链接 推了半个下午..写的三重超时了  加了点单调队列的思想 优化了下过了 dp[i][j] 第二组的最右边的人选第J个人 那最左边肯定选第j-1个人 肯定是选相邻的 dp[i][j] = min ...

  6. NoClassDefFoundError: javassist/util/proxy/MethodFilter

    Caused by: java.lang.NoClassDefFoundError: javassist/util/proxy/MethodFilter    at org.hibernate.byt ...

  7. bzoj2506

    不知道该给这题贴什么标签了,但是这是一道好题1.注意这道题的询问是满足区间减法的,我们可以把一个询问拆成两个询问离线搞搞,这个思想在后面会见到2.分类的思想,这道题的求相同余数看似很烦,实际上我们发现 ...

  8. Codeigniter夸应用调用model

    Thinkphp里面的model都是可以跨应用调用,ci本身没有实现这个方法.可是稍微修改下,比Thinkphp用起来更容易调用.找到Loader.php文件的地址/system/core/Loade ...

  9. CSS学习笔记——定位position属性的学习

    今天学习之前剩下的一个问题:CSS的position属性.首先归纳出和position相关的问题: position作为一个属性,它一共有哪几个属性值? position常用的属性值有哪几个?分别有什 ...

  10. 使用Spring MVC 的表单控制器SimpleFormController

    以注册过程为例,我们可能会选择继承AbstractController来实现表单的显示,继承AbstractCommandController来实现表单的处理 ,这样是可行的,但必须要维护两个控制器 ...