标量子查询SQL改写
一网友说下面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改写的更多相关文章
- 标量子查询调优SQL
fxnjbmhkk4pp4 select /*+ leading (wb,sb,qw) */ 'blocker('||wb.holding_session||':'||sb.username||')- ...
- 优化有标量子查询的SQL
数据库环境:SQL SERVER 2008R2 今天在数据库中抓出一条比较耗费资源的SQL,只返回904条数据,居然跑了40多分钟.SQL及对应的数据量如下图: SELECT saft04.cur_y ...
- 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 ...
- SQL Server的优化器会缓存标量子查询结果集吗
在这篇博客"ORACLE当中自定义函数性优化浅析"中,我们介绍了通过标量子查询缓存来优化函数性能: 标量子查询缓存(scalar subquery caching)会通过缓存结果减 ...
- SQL优化-标量子查询(数据仓库设计的隐患-标量子查询)
项目数据库集群出现了大规模节点宕机问题.经查询,问题在于几张表被锁.主要问题在于近期得几个项目在数据库SQL编写时大量使用了标量子查询. 为确定为题确实是由于数据表访问量超过单节点限制,做了一些测试. ...
- [20180626]函数与标量子查询14.txt
[20180626]函数与标量子查询14.txt --//前面看http://www.cnblogs.com/kerrycode/p/9099507.html链接,里面提到: 通俗来将,当使用标量子查 ...
- SELECT列表中的标量子查询
发现了一种表连接新的写法,以前还没有这样写过或者见别人写过.跟同学聊天他们公司却很多人这样写,看来真的要学学sql了 表 CREATE TABLE `t_book` ( `FId` ) NOT NUL ...
- WHERE 子句中的标量子查询
标量子查询不仅可以用在SELECT 语句的列表中,它还可以用在WHERE 子句中,而且实际应用中子查询很多的时候都是用在WHERE子句中的. 先来看一个简单的例子,我们要检索喜欢“Story”的读者主 ...
- 在MySQL中使用子查询和标量子查询的基本用法
一.MySQL 子查询 子查询是将一个 SELECT 语句的查询结果作为中间结果,供另一个 SQL 语句调用.MySQL 支持 SQL 标准要求的所有子查询格式和操作,也扩展了特有的几种特性.子查询没 ...
随机推荐
- python __builtins__ type类 (69)
69.'type', 返回对象类型 class type(object) | type(object_or_name, bases, dict) | type(object) -> the ob ...
- [Swift]有用的Binary Heap Type类
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- Luogu P1429 平面最近点对 【分治】By cellur925
题目传送门 题目大意:给定平面上n个点,找出其中的一对点的距离,使得在这n个点的所有点对中,该距离为所有点对中最小的.$n$<=100000. $Algorithm$ 最朴素的$n^2$枚举肯定 ...
- jQuery笔记之工具方法extend插件扩展
jQuery工具方法 $.extend()插件扩展(工具方法) $.fn.extend()插件扩展(实例方法) 浅度克隆.深度克隆 两个方法基本是一样的,唯一不同的就是调用方式不一样 -------- ...
- selenium自动化测试实例
11.1使用JavaScripExecutor单击元素 被测试网页:http://www.sogou.com Java代码 public class NewTest { WebDriver ...
- 微信BUG之微信内置的浏览器中window.location.href 不跳转
最近做微信开发遇到这个问题,查了一些文档,总结一下 1.url后面加参数 indow.location.href = url +'?timestamp='+ new Date().getTime()+ ...
- nginx中常见的变量
$arg_PARAMETER 客户端GET请求PARAMETER的值. $args 请求中的参数. $binary_remote_addr 二进制码形式的客户端地址. $body ...
- 在nginx上部署vue项目(history模式)--demo实列;
在很早之前,我写了一篇 关于 在nginx上部署vue项目(history模式) 但是讲的都是理论,所以今天做个demo来实战下.有必要让大家更好的理解,我发现搜索这类似的问题还是挺多的,因此在写一篇 ...
- ionic back 返回按钮不正常显示&&二级路由点击返回按钮失效无法返回到上一级页面的问题
很多时候,app不只有一两级路由,还要三四级路由,但是在ionic中,给出的返回键三级或四级无法使用,所以得自定义方法设置返回. 直接贴代码: <ion-nav-buttons side=&qu ...
- AJPFX关于对集合中的元素删除操作和注意点
import java.util.ArrayList;import java.util.Iterator;import java.util.List; public class ForeTest2 { ...