一网友说下面sql跑的好慢,让我看看

sql代码:

select er,
cid,
pid,
tbl,
zs,
sy,
(select count(sr.mobile_tele_no)
from tbl_sp_sales_records sr
where sr.task_id = tid
and sr.channel_id = cid
and sr.is_conn = '1'
and sr.sales_time >='2017-10-01 00:00:00'
and sr.sales_time <='2017-10-27 00:00:00'
) hc1,
(select count(sr.mobile_tele_no)
from tbl_sp_sales_records sr
where sr.task_id = tid
and sr.channel_id = cid
and sr.is_conn = '0'
and sr.sales_time >='2017-10-01 00:00:00'
and sr.sales_time <='2017-10-27 00:00:00'
) hc2,
(select count(1)
from tbl_disturb_customer_records cr
where cr.target_name = tbl
and cr.disturb_type in ('98', '99')) gz,
(select count(1)
from tbl_disturb_customer_records cr
where cr.target_name = tbl
and cr.disturb_type not in ('98', '99')) mr
from (select c.creator er,
tt.target_data tbl,
t.channel_id cid,
c.create_time ctime,
t.task_id tid,
c.campaign_id pid,
count_table_num_by_channelid(tt.target_data, t.channel_id) zs,
count_table_num(tt.target_data) sy
from tbl_sp_campaign c,
tbl_sp_task t,
tbl_task_targetdata tt
where c.campaign_id = t.campaign_id
and t.task_id = tt.task_id
and c.creator in ('fuzhou',
'lingde',
'longyan',
'nanping',
'putian',
'quanzhou',
'sanming',
'xiamen',
'zhangzhou')
and c.create_time >= '2017-10-01 00:00:00'
and c.create_time <= '2017-10-27 00:00:00')

执行计划

PLAN_TABLE_OUTPUT
Plan hash value: 2087309529 --------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5 | 670 | 14 (8)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 74 | | |
|* 2 | TABLE ACCESS BY INDEX ROWID | TBL_SP_SALES_RECORDS | 1 | 74 | 9 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | IDX_SSR_STAREA | 7 | | 4 (0)| 00:00:01 |
| 4 | SORT AGGREGATE | | 1 | 74 | | |
|* 5 | TABLE ACCESS BY INDEX ROWID | TBL_SP_SALES_RECORDS | 1 | 74 | 9 (0)| 00:00:01 |
|* 6 | INDEX RANGE SCAN | IDX_SSR_STAREA | 7 | | 4 (0)| 00:00:01 |
| 7 | SORT AGGREGATE | | 1 | 26 | | |
|* 8 | TABLE ACCESS BY INDEX ROWID | TBL_DISTURB_CUSTOMER_RECORDS | 289 | 7514 | 82 (0)| 00:00:01 |
|* 9 | INDEX RANGE SCAN | IDX_TARGET_NAME | 2993 | | 20 (0)| 00:00:01 |
| 10 | SORT AGGREGATE | | 1 | 26 | | |
|* 11 | TABLE ACCESS BY INDEX ROWID | TBL_DISTURB_CUSTOMER_RECORDS | 4058 | 103K| 82 (0)| 00:00:01 |
|* 12 | INDEX RANGE SCAN | IDX_TARGET_NAME | 2993 | | 20 (0)| 00:00:01 |
|* 13 | HASH JOIN | | 5 | 670 | 14 (8)| 00:00:01 |
|* 14 | HASH JOIN | | 5 | 450 | 11 (10)| 00:00:01 |
|* 15 | TABLE ACCESS BY INDEX ROWID| TBL_SP_CAMPAIGN | 5 | 225 | 7 (0)| 00:00:01 |
|* 16 | INDEX RANGE SCAN | IDX_P_CREATE_TIME | 6 | | 2 (0)| 00:00:01 |
| 17 | TABLE ACCESS FULL | TBL_SP_TASK | 112 | 5040 | 3 (0)| 00:00:01 |
| 18 | TABLE ACCESS FULL | TBL_TASK_TARGETDATA | 112 | 4928 | 3 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id):
--------------------------------------------------- 2 - filter("SR"."TASK_ID"=:B1 AND "SR"."CHANNEL_ID"=:B2 AND "SR"."IS_CONN"='1')
3 - access("SR"."SALES_TIME">='2017-10-01 00:00:00' AND "SR"."SALES_TIME"<='2017-10-27 00:00:00')
filter(SUBSTR("SALES_TIME",1,10)>='2017-10-01' AND SUBSTR("SALES_TIME",1,10)<='2017-10-27')
5 - filter("SR"."TASK_ID"=:B1 AND "SR"."CHANNEL_ID"=:B2 AND "SR"."IS_CONN"='0')
6 - access("SR"."SALES_TIME">='2017-10-01 00:00:00' AND "SR"."SALES_TIME"<='2017-10-27 00:00:00')
filter(SUBSTR("SALES_TIME",1,10)>='2017-10-01' AND SUBSTR("SALES_TIME",1,10)<='2017-10-27')
8 - filter("CR"."DISTURB_TYPE"='98' OR "CR"."DISTURB_TYPE"='99')
9 - access("CR"."TARGET_NAME"=:B1)
11 - filter("CR"."DISTURB_TYPE"<>'98' AND "CR"."DISTURB_TYPE"<>'99')
12 - access("CR"."TARGET_NAME"=:B1)
13 - access("T"."TASK_ID"="TT"."TASK_ID")
14 - access("C"."CAMPAIGN_ID"="T"."CAMPAIGN_ID")
15 - filter("C"."CREATOR"='fuzhou' OR "C"."CREATOR"='lingde' OR "C"."CREATOR"='longyan' OR
"C"."CREATOR"='nanping' OR "C"."CREATOR"='putian' OR "C"."CREATOR"='quanzhou' OR
"C"."CREATOR"='sanming' OR "C"."CREATOR"='xiamen' OR "C"."CREATOR"='zhangzhou')
16 - access("C"."CREATE_TIME">='2017-10-01 00:00:00' AND "C"."CREATE_TIME"<='2017-10-27 00:00:00')

分析

我跟网友说:让他去掉sql里的标量,运行一次,他说很快

性能瓶颈在于标量子查询上,大家都知道,标量子查询可以改写成left join

改写后代码

select er,
cid,
pid,
tbl,
zs,
sy,
p. hc1,
p. hc2,
p2.gz,
p2. mr
from (select c.creator er,
tt.target_data tbl,
t.channel_id cid,
c.create_time ctime,
t.task_id tid,
c.campaign_id pid,
count_table_num_by_channelid(tt.target_data, t.channel_id) zs,
count_table_num(tt.target_data) sy
from tbl_sp_campaign c, tbl_sp_task t, tbl_task_targetdata tt
where c.campaign_id = t.campaign_id
and t.task_id = tt.task_id
and c.creator in ('fuzhou',
'lingde',
'longyan',
'nanping',
'putian',
'quanzhou',
'sanming',
'xiamen',
'zhangzhou')
and c.create_time >= '2017-10-01 00:00:00'
and c.create_time <= '2017-10-27 00:00:00') c
left join (select
sr.task_id,
sr.channel_id,
count(decode(sr.is_conn,1,sr.mobile_tele_no)) hc1,
count(decode(sr.is_conn,0,sr.mobile_tele_no)) hc2,
from tbl_sp_sales_records sr
where sr.sales_time >='2017-10-01 00:00:00'
and sr.sales_time <='2017-10-27 00:00:00'
group by sr.task_id,sr.channel_id)p
on (p.task_id = c.tid and p.channel_id = c.cid)
left join (select
count(case when disturb_type in ('98', '99') then 1 end )gz,
count(case when disturb_type not in ('98', '99') then 1 end )mr,
target_name
from tbl_disturb_customer_records
group by target_name) p2
on (p2.target_name = c.tbl)

执行计划



PLAN_TABLE_OUTPUT
Plan hash value: 4214787203 -----------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5 | 1160 | 435 (1)| 00:00:06 |
| 1 | NESTED LOOPS OUTER | | 5 | 1160 | 435 (1)| 00:00:06 |
|* 2 | HASH JOIN | | 5 | 1020 | 25 (12)| 00:00:01 |
|* 3 | HASH JOIN OUTER | | 5 | 800 | 21 (10)| 00:00:01 |
|* 4 | HASH JOIN | | 5 | 450 | 11 (10)| 00:00:01 |
|* 5 | TABLE ACCESS BY INDEX ROWID | TBL_SP_CAMPAIGN | 5 | 225 | 7 (0)| 00:00:01 |
|* 6 | INDEX RANGE SCAN | IDX_P_CREATE_TIME | 6 | | 2 (0)| 00:00:01 |
| 7 | TABLE ACCESS FULL | TBL_SP_TASK | 112 | 5040 | 3 (0)| 00:00:01 |
| 8 | VIEW | | 7 | 490 | 10 (10)| 00:00:01 |
| 9 | HASH GROUP BY | | 7 | 518 | 10 (10)| 00:00:01 |
| 10 | TABLE ACCESS BY INDEX ROWID| TBL_SP_SALES_RECORDS | 7 | 518 | 9 (0)| 00:00:01 |
|* 11 | INDEX RANGE SCAN | IDX_SSR_STAREA | 7 | | 4 (0)| 00:00:01 |
| 12 | TABLE ACCESS FULL | TBL_TASK_TARGETDATA | 112 | 4928 | 3 (0)| 00:00:01 |
| 13 | VIEW PUSHED PREDICATE | | 1 | 28 | 82 (0)| 00:00:01 |
| 14 | SORT GROUP BY | | 1 | 26 | 82 (0)| 00:00:01 |
| 15 | TABLE ACCESS BY INDEX ROWID | TBL_DISTURB_CUSTOMER_RECORDS | 4342 | 110K| 82 (0)| 00:00:01 |
|* 16 | INDEX RANGE SCAN | IDX_TARGET_NAME | 2993 | | 20 (0)| 00:00:01 |
----------------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id):
--------------------------------------------------- 2 - access("T"."TASK_ID"="TT"."TASK_ID")
3 - access("P"."CHANNEL_ID"(+)="T"."CHANNEL_ID" AND "P"."TASK_ID"(+)="T"."TASK_ID")
4 - access("C"."CAMPAIGN_ID"="T"."CAMPAIGN_ID")
5 - filter("C"."CREATOR"='fuzhou' OR "C"."CREATOR"='lingde' OR "C"."CREATOR"='longyan' OR
"C"."CREATOR"='nanping' OR "C"."CREATOR"='putian' OR "C"."CREATOR"='quanzhou' OR "C"."CREATOR"='sanming'
OR "C"."CREATOR"='xiamen' OR "C"."CREATOR"='zhangzhou')
6 - access("C"."CREATE_TIME">='2017-10-01 00:00:00' AND "C"."CREATE_TIME"<='2017-10-27 00:00:00')
11 - access("SR"."SALES_TIME">='2017-10-01 00:00:00' AND "SR"."SALES_TIME"<='2017-10-27 00:00:00')
filter(SUBSTR("SALES_TIME",1,10)>='2017-10-01' AND SUBSTR("SALES_TIME",1,10)<='2017-10-27')
16 - access("TARGET_NAME"="TT"."TARGET_DATA")

如果大家有兴趣,可以拿着以下sql代码进行测试。

改写前的:

select d.department_id,
d.department_name,
d.location_id,
NVL((select SUM(e.salary)
from employees e
where e.department_id = d.department_id
and e.job_id = 'IT_PROG'),
0) IT_SAL,
NVL((select SUM(e.salary)
from employees e
where e.department_id = d.department_id
and e.job_id = 'AD_VP'),
0) VP_SAL,
NVL((select SUM(e.salary)
from employees e
where e.department_id = d.department_id
and e.job_id = 'FI_ACCOUNT'),
0) FI_SAL,
NVL((select SUM(e.salary)
from employees e
where e.department_id = d.department_id
and e.job_id = 'PU_CLERK'),
0) PU_SAL
from departments d

改写后的:

select d.department_id,
d.department_name,
d.location_id,
nvl(c.it_sal1,0) it_sal ,
nvl(c.vp_sal1,0) vp_sal ,
nvl(c.fi_sal1,0) fi_sal ,
nvl(c.pu_sal1,0) pu_sal
from departments d
left join (select sum(case when e.job_id='IT_PROG' then e.salary end) it_sal1 ,
sum(case when e.job_id='AD_VP' then e.salary end) vp_sal1 ,
sum(case when e.job_id='FI_ACCOUNT' then e.salary end) fi_sal1 ,
sum(case when e.job_id='PU_CLERK' then e.salary end) pu_sal1,
e.department_id
from employees e group by e.department_id) c
on d.department_id=c.department_id ;

标量子查询SQL改写的更多相关文章

  1. 标量子查询调优SQL

    fxnjbmhkk4pp4 select /*+ leading (wb,sb,qw) */ 'blocker('||wb.holding_session||':'||sb.username||')- ...

  2. 优化有标量子查询的SQL

    数据库环境:SQL SERVER 2008R2 今天在数据库中抓出一条比较耗费资源的SQL,只返回904条数据,居然跑了40多分钟.SQL及对应的数据量如下图: SELECT saft04.cur_y ...

  3. Oracle sql优化之分析函数优化标量子查询

    待优化语句如下 select a.code as code, a.m_code as m_code,a.stktype as f_stype,a.e_year as e_year, b.sname a ...

  4. SQL Server的优化器会缓存标量子查询结果集吗

    在这篇博客"ORACLE当中自定义函数性优化浅析"中,我们介绍了通过标量子查询缓存来优化函数性能: 标量子查询缓存(scalar subquery caching)会通过缓存结果减 ...

  5. SQL优化-标量子查询(数据仓库设计的隐患-标量子查询)

    项目数据库集群出现了大规模节点宕机问题.经查询,问题在于几张表被锁.主要问题在于近期得几个项目在数据库SQL编写时大量使用了标量子查询. 为确定为题确实是由于数据表访问量超过单节点限制,做了一些测试. ...

  6. [20180626]函数与标量子查询14.txt

    [20180626]函数与标量子查询14.txt --//前面看http://www.cnblogs.com/kerrycode/p/9099507.html链接,里面提到: 通俗来将,当使用标量子查 ...

  7. SELECT列表中的标量子查询

    发现了一种表连接新的写法,以前还没有这样写过或者见别人写过.跟同学聊天他们公司却很多人这样写,看来真的要学学sql了 表 CREATE TABLE `t_book` ( `FId` ) NOT NUL ...

  8. WHERE 子句中的标量子查询

    标量子查询不仅可以用在SELECT 语句的列表中,它还可以用在WHERE 子句中,而且实际应用中子查询很多的时候都是用在WHERE子句中的. 先来看一个简单的例子,我们要检索喜欢“Story”的读者主 ...

  9. 在MySQL中使用子查询和标量子查询的基本用法

    一.MySQL 子查询 子查询是将一个 SELECT 语句的查询结果作为中间结果,供另一个 SQL 语句调用.MySQL 支持 SQL 标准要求的所有子查询格式和操作,也扩展了特有的几种特性.子查询没 ...

随机推荐

  1. python __builtins__ type类 (69)

    69.'type', 返回对象类型 class type(object) | type(object_or_name, bases, dict) | type(object) -> the ob ...

  2. [Swift]有用的Binary Heap Type类

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  3. Luogu P1429 平面最近点对 【分治】By cellur925

    题目传送门 题目大意:给定平面上n个点,找出其中的一对点的距离,使得在这n个点的所有点对中,该距离为所有点对中最小的.$n$<=100000. $Algorithm$ 最朴素的$n^2$枚举肯定 ...

  4. jQuery笔记之工具方法extend插件扩展

    jQuery工具方法 $.extend()插件扩展(工具方法) $.fn.extend()插件扩展(实例方法) 浅度克隆.深度克隆 两个方法基本是一样的,唯一不同的就是调用方式不一样 -------- ...

  5. selenium自动化测试实例

    11.1使用JavaScripExecutor单击元素 被测试网页:http://www.sogou.com Java代码 public class NewTest {      WebDriver  ...

  6. 微信BUG之微信内置的浏览器中window.location.href 不跳转

    最近做微信开发遇到这个问题,查了一些文档,总结一下 1.url后面加参数 indow.location.href = url +'?timestamp='+ new Date().getTime()+ ...

  7. nginx中常见的变量

    $arg_PARAMETER        客户端GET请求PARAMETER的值. $args     请求中的参数. $binary_remote_addr 二进制码形式的客户端地址. $body ...

  8. 在nginx上部署vue项目(history模式)--demo实列;

    在很早之前,我写了一篇 关于 在nginx上部署vue项目(history模式) 但是讲的都是理论,所以今天做个demo来实战下.有必要让大家更好的理解,我发现搜索这类似的问题还是挺多的,因此在写一篇 ...

  9. ionic back 返回按钮不正常显示&&二级路由点击返回按钮失效无法返回到上一级页面的问题

    很多时候,app不只有一两级路由,还要三四级路由,但是在ionic中,给出的返回键三级或四级无法使用,所以得自定义方法设置返回. 直接贴代码: <ion-nav-buttons side=&qu ...

  10. AJPFX关于对集合中的元素删除操作和注意点

    import java.util.ArrayList;import java.util.Iterator;import java.util.List; public class ForeTest2 { ...