生产环境sql语句调优实战第三篇

生产环境有一条sql语句执行比较频繁,占用了大量的cpu资源。原本执行需要花费11秒。在一次排查中引起了我的注意,决定看看cpu消耗到底在哪儿?
sql语句是比较简单的,通过查询SUBSCRIBER_FA_V是一个视图。在视图中关联了几个和业务核心表。

SELECT TO_CHAR(SUBSCRIBER_NO) SUBSCRIBER_ID,
       SUB_STATUS,
       SUB_STS_RSN_CD,
       TO_CHAR(SUB_STATUS_DATE, 'yyyyMMdd') SUB_STATUS_DATE,
       SUBSCRIBER_TYPE
  FROM SUBSCRIBER_FA_V
 WHERE BAN = :1
   AND ROWNUM :2
   AND SUB_STATUS NOT IN ('C', 'L', 'T')
 ORDER BY INIT_ACT_DATE, SUBSCRIBER_NO

如果想做sql检查,对于sql中传入的变量,sql monitor提供了很方便的功能。
Binds

Name Position Type Value
:B2 1 NUMBER 10308170
:B1 2 NUMBER 6

很清晰看到正在执行的sql语句对应的变量值。

还是来看看执行计划。

SQL Plan Monitoring Details (Plan Hash Value=1125972187)

Id Operation Name Estimated
Rows
Cost Active Period 
(11s)
Execs Rows Memory
(Max)
Temp 
(Max)
IO Requests CPU Activity Wait Activity

.

0 SELECT STATEMENT
.


.


.

.

.

1 1
.


.


.


.


.

1 . SORT ORDER BY
.

6 67758

.

.

1 1 2.0KB
.


.


.


.

2 .. COUNT STOPKEY
.


.


.

.

.

1 1
.


.


.


.


.

3 ... VIEW SUBSCRIBER_FA_V 577K 59898

.

.

1 1
.


.


.


.


.

4 .... SORT UNIQUE STOPKEY
.

577K 59898

.

.

1 1 2.0KB
.


.


.


.

5 ..... UNION-ALL
.


.


.

.

.

.

1 1
.


.


.


.


.

6 ......NESTED LOOPS
.


.


.

.

.

.

1 1
.


.


.


.


.

7 .......NESTED LOOPS
.

1 3

.

.

.

1 1
.


.


.


.


.

8 ........NESTED LOOPS
.

1 2

.

.

.

1 1
.


.


.


.


.

9 .........INDEX RANGE SCAN CHANNEL_1IX 1 1

.

.

.

1 1
.


.


.


.


.

10 .........TABLE ACCESS BY INDEX ROWID DISTRIBUTE 1 1

.

.

.

1 1
.


.


.


.


.

11 ..........INDEX RANGE SCAN DISTRIBUTE_3IX 1 1

.

.

.

1 1
.


.


.


.


.

12 ........INDEX UNIQUE SCAN SUBSCRIBER_PK 1 1

.

.

.

1 1
.


.


.


.


.

13 ....... TABLE ACCESS BY INDEX ROWID SUBSCRIBER 1 1

.

.

.

1 1
.


.


.


.


.

14 ...... VIEW
.

577K 35591

.

.

1 0
.


.

.

20%

.

15 .......WINDOW SORT PUSHED RANK
.

577K 35591

.

.

1 522K 21.2MB 63.0MB

.

.

627 (38%)

.

40%

.

33%

.

16 ........ HASH JOIN
.

577K 23809

.

.

1 550K 23.4MB 88.0MB

.

.

390 (23%)

.

.

66%

.

17 .........INDEX FULL SCAN CHANNEL_1IX 1M 1269

.

.

.

1 1M
.


.


.


.


.

18 .........HASH JOIN
.

577K 18648

.

.

.

1 550K 30.7MB 40.0MB

.

53 (3.2%)

.

20%

.

19 ..........TABLE ACCESS FULL SUBSCRIBER 430K 8704

.

.

.

1 424K
.


.

.

20%

.

20 ..........TABLE ACCESS FULL DISTRIBUTE 2M 6046

.

.

.

1 2M
.


.


.


.

性能瓶颈都在几个全表扫描和一个分析函数相关的rank操作中。毕竟返回的记录数只有1条。如果过多的资源都消耗在一些不正确的连接访问中,是完全可以避免的。

视图的内容如下:
SELECT xxxxxxx
          1 RANK
     FROM subscriber, distribute ed, channel cpc
    WHERE     cpc.pym_channel_no = ed.target_pcn
          AND ed.agreement_no = subscriber.subscriber_no
          AND eg_dist_type = 'D'
          AND ed.expiration_date IS NULL
          AND SUBSCRIBER.SUB_STATUS NOT IN ('C', 'L', 'T')
   UNION
   SELECT xxxxxxx
     FROM (SELECT cpc.ban,
                  subscriber.prim_resource_val,
                  subscriber.init_act_date,
                  SUBSCRIBER.CUSTOMER_ID,
                  subscriber.subscriber_no,
                  SUBSCRIBER.SUBSCRIBER_TYPE,
                  SUBSCRIBER.SUB_STATUS,
                  SUBSCRIBER.SUB_STS_RSN_CD,
                  SUBSCRIBER.SUB_STATUS_DATE,
                  SUBSCRIBER.EFFECTIVE_DATE,
                  ROW_NUMBER ()
                  OVER (
                     PARTITION BY subscriber.subscriber_no
                     ORDER BY
                        ed.expiration_date, subscriber.subscriber_no DESC)
                     AS RANK
             FROM subscriber, distribute ed, channel cpc
            WHERE     cpc.pym_channel_no = ed.target_pcn
                  AND ed.agreement_no = subscriber.subscriber_no
                  AND eg_dist_type = 'D'
                  AND SUBSCRIBER.SUB_STATUS IN ('C', 'L', 'T'))
    WHERE RANK = 1

根据执行计划,出问题的正式标黄的union子句。
根据传入的参数,是可以走索引的,但是在Union子句中,嵌入了子查询,导致在整个视图在数据的访问中,先全表扫描整个子查询,然后再匹配传入的参数。
视图的内容是不能随便改的,可能在这种场景中合适,其他的相关查询就有问题了。
所以尝试把视图的内容直接转换成直接的sql,标黄的部分是做的相应改动。

select xxxxxxx
  from (SELECT xxxxxxx
               1 RANK
          FROM subscriber, event_distribute ed, csm_pay_channel cpc
         WHERE cpc.pym_channel_no = ed.target_pcn
           AND ed.agreement_no = subscriber.subscriber_no
           AND eg_dist_type = 'D'
           AND ed.expiration_date IS NULL
           AND SUBSCRIBER.SUB_STATUS NOT IN ('C', 'L', 'T')
           and cpc.ban = 10308170
        UNION
        SELECT "SUBSCRIBER_NO",
               "INIT_ACT_DATE",
               "SUB_STATUS",
               "SUB_STS_RSN_CD",
               "SUB_STATUS_DATE",
               "SUBSCRIBER_TYPE",
               "RANK"
          FROM (SELECT subscriber.subscriber_no,
                       SUBSCRIBER.INIT_ACT_DATE,
                       SUBSCRIBER.SUBSCRIBER_TYPE,
                       SUBSCRIBER.SUB_STATUS,
                       SUBSCRIBER.SUB_STS_RSN_CD,
                       SUBSCRIBER.SUB_STATUS_DATE,
                       ROW_NUMBER() OVER(PARTITION BY subscriber.subscriber_no ORDER BY ed.expiration_date, subscriber.subscriber_no DESC) AS RANK
                  FROM subscriber, event_distribute ed, csm_pay_channel cpc
                 WHERE cpc.pym_channel_no = ed.target_pcn
                   AND ed.agreement_no = subscriber.subscriber_no
                   AND eg_dist_type = 'D'
                   AND SUBSCRIBER.SUB_STATUS IN ('C', 'L', 'T')
                   and cpc.ban = 10308170)
         WHERE RANK = 1)
 where SUB_STATUS NOT IN ('C','L','T') and rownum
 ORDER BY INIT_ACT_DATE, SUBSCRIBER_ID

看似语句挺长的,但是走了索引执行效率还是很高的。

Elapsed: 00:00:00.01

Statistics

----------------------------------------------------------

         
0  recursive calls

         
0  db block gets

         22  consistent gets

         
0  physical reads

         
0  redo size

       
857  bytes sent via SQL*Net to client

       
520  bytes received via SQL*Net from client

         
2  SQL*Net roundtrips to/from client

         
3  sorts (memory)

         
0  sorts (disk)

         
1  rows processed

时间: 2024-10-26 02:21:11

生产环境sql语句调优实战第三篇的相关文章

生产环境sql语句调优实战第十篇

陆陆续续写了九篇关于生产环境sql语句的调优案例,发现了不少问题,可能有些问题回头来看是比较低级的错误,稍加改动就能够运行在秒级,有些可能是在秒级到毫秒级的小步提升等等,不管调优的改进多大,从dba的角度来看,好多问题都是基于资源来调优的,比如添加索引,降低IO,降低CPU消耗,提高CPU利用率等等.如果有时候从业务角度来下下功夫,可能某种程度上效果要更好于基于资源/代价的调优. 最近客户反馈有几条sql语句IO消耗很高,希望我们能够给提点建议. sql语句很短,但是运行时间在9秒左右.运行频率

生产环境sql语句调优实战第八篇

生产环境中的sql语句执行时间是很关键的性能指标,如果某个sql语句执行几个小时,优化以后几分钟,几十秒的话.会有很大的成就感,同时如果某个sql语句执行10秒,能够优化到1秒,感觉提升的幅度不是很大,但是如果这条语句执行极为频繁的话,那这种调优还是更有成就感的. 执行时间是sql调优的一把标尺,但是同时也需要考虑到系统资源的平衡. 今天在系统中发现一条sql语句执行时间很长.平均一个查询要执行一个半小时左右,而且系统的资源消耗极大. 需要说明的service_details 是数据量过亿的表.

生产环境sql语句调优实战第六篇

生产环境中有大量的sql语句在运行,尽管有awr,ash做数据的收集统计,但是dba的调优工作大多数情况都是在问题已经发生后做排查的,有些sql语句可能执行的时间有1,2分钟左右,但是sql语句本身有潜在的性能问题,通过awr是定位不到的,ash尽管能够查到,但是我们在未知的情况下怎么知道问题发生的精确时间点,通过sql monitor能够查到一些实时的性能问题,但是还是需要按照自己的情况和要求来不间断地进行性能的监控.通过一个工具一劳永逸是不现实的. 今天想做数据迁移也有些日子了,看看生产环境

生产环境sql语句调优实战第七篇

在数据迁移完成之后,开始了例行的后期数据库维护,早上一来就发现了一个sql执行时间很长了.达到了37279秒.最后在改进调优之后执行速度在1分钟以内. 这个速度是毫无疑问的性能问题,但是是否是因为数据迁移直接导致的呢,通过简单的脚本分析,得出了如下的图表. 显示了同样的sql语句在7月份至今的执行情况,还真是奇怪,昨天以前一直正常,期间也进行过两次数据迁移,昨天的数据迁移完成以后,性能就出奇的差. 通过sql_monitor得到了执行计划和对应的sql语句. 可以看到执行时间是昨天的下午,一直执

生产环境sql语句调优实战第四篇

生产中有一条sql语句消耗了大量的cpu资源,执行时间在18秒左右, Session : PRODBUSER (1560:61133) SQL ID : 1hg2wcuapy3y3 SQL Execution ID : 16871963 Execution Started : 07/21/2014 12:30:20 First Refresh Time : 07/21/2014 12:30:24 Last Refresh Time : 07/21/2014 12:30:37 Duration :

生产环境sql语句调优实战第九篇

生产环境中有一些sql语句是不定时炸弹,不声不响的运行着,可能相关的表很大,运行时间达数小时甚至数天. 上周在生产环境中发现一条sql语句,运行时间几乎是按照天来计算的.看到这种sql语句,就希望能够马上能够找到立竿见影的效果,不过欲速则不达,需要做不少工作.一定要反复验证可行. sql语句的运行情况如下: SQL Execution ID : 16777217  Execution Started : 10/18/2014 11:46:30  First Refresh Time : 10/1

生产环境sql语句调优实战第二篇

在生产环境通过sql monitor监控到有一条sql执行效率很差.执行了大约5个小时,得到的sql monitor报告如下: Global Information: EXECUTING Instance ID : 1 Buffer Gets IO Requests Database Time Wait Activity . 40M . 17M . . 8450s . . . 100% Session : PRODUSER(14:22343) SQL ID : fkzafpjs28d6d SQL

生产环境大型sql语句调优实战第一篇(一)

在生产环境中有一条sql语句的性能极差,在早晨非高峰时段运行抽取数据,平均要花费40分钟,有时候竟然要跑10个多小时.sql语句比较长,需要点耐心往下看.我对表的数据量都做了简单的说明. 首先拿到sql语句,一看到关联的表有一长串,而且都是很大的表.如果性能很差,可能和走全表扫描有关,还有可能和多表关联时,表的查取顺序也有一定的关系. SELECT   DISTINCT CA.L9_CONVERGENCE_CODE AS ATB2,                 CU.CUST_SUB_TYP

生产环境大型sql语句调优实战第一篇(二)

继续昨天的部分,上一篇的链接为: http://blog.itpub.net/23718752/viewspace-1217012/ 对这条大sql的性能瓶颈进行了分析.主要瓶颈在于一个很大的业务表,数据量在亿级.如果通过时间条件来过滤,会有5%以内的数据被过滤出来. 但是没有时间相关的索引字段,所以会走全表扫描,在目前的产品线中,这个大分区表的索引时严格控制的,所以最后经过测试和比对,还是考虑加并行来提高数据的查取速度. --查找性能瓶颈,根据反馈,查取的数据其实并不错,可能在几千条以内的样子