ITPub博客

首页 > 数据库 > Oracle > Oracle 优化之SQL(清晰的逻辑重构业务SQL)

Oracle 优化之SQL(清晰的逻辑重构业务SQL)

原创 Oracle 作者:lovehewenyu 时间:2016-07-12 10:39:13 0 删除 编辑

高效的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博客 ” ,链接:https://blog.itpub.net/26442936/viewspace-2121889/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
10年金融行业老鸟。Oracle,Mysql,PostgreSQL,EMC 存储,NBU备份。微信/电话 18211103995

注册时间:2012-02-03

  • 博文量
    307
  • 访问量
    1528525