高效的SQL(清晰的逻辑重构业务SQL)

高效的SQL(清晰的逻辑重构业务SQL) 


业务SQL如下
select to_char(t.entertime, 'yyyymmdd') AS time,
       t.userid,
       --振铃通话时间
       sum(ROUND(TO_NUMBER(t.turnontime - t.ringtime) * 24 * 60 * 60)) AS t_ring,
       --进线量
       count(case
               when (((select ceil((t1.custhanguptime - t1.ringtime) * 24 * 60 * 60) sh
                         FROM doudou t1
                        where t1.custhanguptime is not null and t1.callid=t.callid
                          and t1.ringtime is not null) > 5 or
                    (t.custhanguptime is null))) then
                1
               else
                null
             end) as n_enter,
       --呼入通话时长
       sum(ROUND(TO_NUMBER(t.hanguptime - t.turnontime) * 24 * 60 * 60)) AS t_inbound
  from doudou t
 where  t.ringtime is not null
 Group by to_char(t.entertime, 'yyyymmdd'), t.userid;


索引如下 
alter table DOUDOU
  add constraint DOUDOU_PK_CALLID primary key (CALLID)
  using index 
  tablespace CMSDATA
  pctfree 10
  initrans 2
  maxtrans 255
  storage
  (
    initial 64K
    next 1M
    minextents 1
    maxextents unlimited
  );
  


Elapsed: 00:00:13.96


Execution Plan
----------------------------------------------------------
Plan hash value: 2637126917


------------------------------------------------------------------------------------------------
| Id  | Operation                   | Name             | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                  |   691K|    45M|  5971   (3)| 00:01:12 |
|*  1 |  TABLE ACCESS BY INDEX ROWID| DOUDOU           |     1 |    30 |     3   (0)| 00:00:01 |
|*  2 |   INDEX UNIQUE SCAN         | DOUDOU_PK_CALLID |     1 |       |     2   (0)| 00:00:01 |
|   3 |  HASH GROUP BY              |                  |   691K|    45M|  5971   (3)| 00:01:12 |
|*  4 |   TABLE ACCESS FULL         | DOUDOU           |   691K|    45M|  5921   (2)| 00:01:12 |
------------------------------------------------------------------------------------------------


Predicate Information (identified by operation id):
---------------------------------------------------


   1 - filter("T1"."CUSTHANGUPTIME" IS NOT NULL AND "T1"."RINGTIME" IS NOT NULL)
   2 - access("T1"."CALLID"=:B1)
   4 - filter("T"."RINGTIME" IS NOT NULL)


Note
-----
   - dynamic sampling used for this statement (level=2)




Statistics
----------------------------------------------------------
         78  recursive calls
          0  db block gets
    1191076  consistent gets  <==逻辑读过多
       4080  physical reads
          0  redo size
     542664  bytes sent via SQL*Net to client
      10904  bytes received via SQL*Net from client
        946  SQL*Net roundtrips to/from client
          6  sorts (memory)
          0  sorts (disk)
      14169  rows processed
      
优化思想
1.解决TAF问题
2.如果解决不了TAF,瘦身DOUDOU这张表的有效数据,这样可以减少consistent gets


1.解决TAF问题
1252852 DOUDOU
563939 ringtime is not null  
1901 ringtime is not null AND custhanguptime is not null 


create index idx_zuhe on doudou (custhanguptime,ringtime,CALLID); 
exec dbms_stats.gather_table_stats(user,'DOUDOU',cascade=>true);
##经过复合索引,效果并不明显。所以选择瘦身DOUDOU表。
##使用分区表进行瘦身


2.如果解决不了TAF,瘦身DOUDOU这张表的有效数据,这样可以减少consistent gets
select to_char(t.entertime, 'yyyymmdd') AS time,
       t.userid,
       --振铃通话时间
       sum(ROUND(TO_NUMBER(t.turnontime - t.ringtime) * 24 * 60 * 60)) AS t_ring,
       --进线量
       count(case
               when (((select ceil((t1.custhanguptime - t1.ringtime) * 24 * 60 * 60) sh
                         FROM doudou t1
                        where t1.custhanguptime is not null and t1.callid=t.callid
                          and t1.ringtime is not null) > 5 or
                    (t.custhanguptime is null))) then
                1
               else
                null
             end) as n_enter,
       --呼入通话时长
       sum(ROUND(TO_NUMBER(t.hanguptime - t.turnontime) * 24 * 60 * 60)) AS t_inbound
  from  doudou t
 where 
   to_char(t.entertime, 'yyyymmdd') like '201607%' and  --重构SQL,瘦身DOUDOU表的有效数据。
 t.ringtime is not null
 Group by to_char(t.entertime, 'yyyymmdd'), t.userid ;
 
194 rows selected.


Elapsed: 00:00:01.76


Execution Plan
----------------------------------------------------------
Plan hash value: 2637126917


--------------------------------------------------------------------------------------------------------
| Id  | Operation                   | Name             | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                  | 28374 |  1246K|       |  6240   (2)| 00:01:15 |
|*  1 |  TABLE ACCESS BY INDEX ROWID| DOUDOU           |     1 |    24 |       |     3   (0)| 00:00:01 |
|*  2 |   INDEX UNIQUE SCAN         | DOUDOU_PK_CALLID |     1 |       |       |     2   (0)| 00:00:01 |
|   3 |  HASH GROUP BY              |                  | 28374 |  1246K|  1800K|  6240   (2)| 00:01:15 |
|*  4 |   TABLE ACCESS FULL         | DOUDOU           | 28374 |  1246K|       |  5914   (2)| 00:01:11 |
--------------------------------------------------------------------------------------------------------


Predicate Information (identified by operation id):
---------------------------------------------------


   1 - filter("T1"."CUSTHANGUPTIME" IS NOT NULL AND "T1"."RINGTIME" IS NOT NULL)
   2 - access("T1"."CALLID"=:B1)
   4 - filter("T"."RINGTIME" IS NOT NULL AND TO_CHAR(INTERNAL_FUNCTION("T"."ENTERTIME"),'yyyymmd
              d') LIKE '201607%')




Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
      44513  consistent gets  <==业务SQL重构后,基本满足需求
          0  physical reads
          0  redo size
       8099  bytes sent via SQL*Net to client
        652  bytes received via SQL*Net from client
         14  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
        194  rows processed 
##根据业务逻辑,瘦身DOUDOU之后逻辑读从1191076优化至44513。优化了26倍
##此业务SQL经跟业务人员沟通,当月的数据就可以满足业务需求。所以重构了业务SQL减少逻辑读。


总结:
优化往往是优化写SQL的一种思想,这种思想的核心就是用最小的数据来完成需求。无关的数据都是"砍!砍!砍!"掉


########################################################################################
版权所有,文章允许转载,但必须以链接方式注明源地址,否则追究法律责任!【QQ交流群:53993419】
QQ:14040928 E-mail:dbadoudou@163.com
本文链接: http://blog.itpub.net/26442936/viewspace-2121889/
########################################################################################

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/26442936/viewspace-2121889/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/26442936/viewspace-2121889/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值