前言

一大早,客户给我打电话说:

xx,应用很慢,查询数据总是超时,让我看看。。。

根据多年DBA经验,首当其冲的肯定是去查询数据库在这段时间都在干嘛。

分析

导出awr报告分析

1). 数据库在此时间段非常繁忙。



2). 查看Top 5 Timed Events,出现了Concurrency等待事件latch: library cache**



3). 查看SQL ordered by Gets,不看不知道,一看吓一跳



4). *50pwxa3bzp7gkSQL语句

select *
from (select d.*, rownum as num
from (SELECT A.BILLNO,
A.BILLCODE,
A.GETDATE,
A.GETUNITCODE,
A.GETCODE,
A.GETORGANCODE,
A.USEORGANCODE,
A.USEDATE,
A.USEUNITCODE,
A.USERCODE,
A.CURRENCYCODE,
A.AMOUNT,
A.NAME,
A.NOTES,
A.STATUSCODE,
A.IFPAGEONHOLE,
A.OPCODE,
A.OPUNITCODE,
A.OPDATE,
A.LOCKTIME,
A.GETAGENTCODE,
(SELECT D.AGENTNAME
FROM SYN_MM_AGENTCODE_TC D
WHERE D.AGENTCODE = A.GETAGENTCODE) AS GETAGENTNAME,
A.USEAGENTCODE,
A.OUTSTATUS,
CASE A.BILLCODE
WHEN 'B2010005' THEN
A.FACTBILLCODE
ELSE
''
END FACTBILLCODE,
A.SALES,
A.FROMDATE,
A.TODATE,
(SELECT BILLNAME
FROM BD_BILLCODE
WHERE BILLCODE = A.BILLCODE) BILLNAME,
(SELECT HANDLERNAME
FROM BD_HANDLER
WHERE HANDLERCODE = A.USERCODE) USERNAME,
(SELECT HANDLERNAME
FROM BD_HANDLER
WHERE HANDLERCODE = A.GETCODE) GETERNAME,
(SELECT NO3
FROM B_BILLDETAIL
WHERE BILLNO = A.BILLNO
AND BILLCODE = A.BILLCODE
AND FACTBILLCODE = A.FACTBILLCODE) ONLINEINVOICENO,
(SELECT NO4
FROM B_BILLDETAIL
WHERE BILLNO = A.BILLNO
AND BILLCODE = A.BILLCODE
AND FACTBILLCODE = A.FACTBILLCODE) ONLINEINVOICECODE
FROM B_BILL A
WHERE 3 > 2
AND 3 > 2
AND 3 > 2
AND 3 > 2
AND 3 > 2
AND TRIM(BILLNO) >= :B1
AND TRIM(BILLNO) <= :B2
AND 3 > 2
AND 3 > 2
AND 3 > 2
AND 3 > 2
AND 3 > 2
AND 3 > 2
ORDER BY A.BILLNO) d
where rownum <= 1)
where num > 0 执行计划:
Plan hash value: 4085294641 ------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 4632 | 9 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL | CHAGENTBASE | 1 | 56 | 6 (0)| 00:00:01 |
| 2 | TABLE ACCESS BY INDEX ROWID | BD_BILLCODE | 1 | 31 | 1 (0)| 00:00:01 |
|* 3 | INDEX UNIQUE SCAN | PK_BD_BILLCODE | 1 | | 0 (0)| 00:00:01 |
| 4 | TABLE ACCESS BY INDEX ROWID | T_EMPLOYEE_VIEW | 1 | 26 | 2 (0)| 00:00:01 |
|* 5 | INDEX RANGE SCAN | IND_T_EMPLOYEE_VIEW | 1 | | 1 (0)| 00:00:01 |
| 6 | TABLE ACCESS BY INDEX ROWID | T_EMPLOYEE_VIEW | 1 | 26 | 2 (0)| 00:00:01 |
|* 7 | INDEX RANGE SCAN | IND_T_EMPLOYEE_VIEW | 1 | | 1 (0)| 00:00:01 |
| 8 | TABLE ACCESS BY INDEX ROWID | B_BILLDETAIL | 1 | 50 | 4 (0)| 00:00:01 |
|* 9 | INDEX RANGE SCAN | PK_B_BILLDETAIL_02 | 1 | | 3 (0)| 00:00:01 |
| 10 | TABLE ACCESS BY INDEX ROWID | B_BILLDETAIL | 1 | 50 | 4 (0)| 00:00:01 |
|* 11 | INDEX RANGE SCAN | PK_B_BILLDETAIL_02 | 1 | | 3 (0)| 00:00:01 |
|* 12 | VIEW | | 1 | 4632 | 9 (0)| 00:00:01 |
|* 13 | COUNT STOPKEY | | | | | |
| 14 | VIEW | | 2 | 9238 | 9 (0)| 00:00:01 |
| 15 | TABLE ACCESS BY INDEX ROWID| B_BILL | 17395 | 3822K| 9 (0)| 00:00:01 |
|* 16 | INDEX FULL SCAN | PK_B_BILL_01 | 2 | | 8 (0)| 00:00:01 |
------------------------------------------------------------------------------------------------------ Predicate Information (identified by operation id):
--------------------------------------------------- 1 - filter("D"."AGENTCODE"=:B1)
3 - access("BILLCODE"=:B1)
5 - access("A"."CODE"=:B1)
7 - access("A"."CODE"=:B1)
9 - access("BILLNO"=:B1 AND "BILLCODE"=:B2 AND "FACTBILLCODE"=:B3)
11 - access("BILLNO"=:B1 AND "BILLCODE"=:B2 AND "FACTBILLCODE"=:B3)
12 - filter("NUM">0)
13 - filter(ROWNUM<=1)
16 - filter(TO_NUMBER(TRIM("BILLNO"))>=601710100010 AND
TO_NUMBER(TRIM("BILLNO"))<=601710100010)

5). 对sql语句进行分析

1、SQL语句中有很多标量子查询,我们可以利用left join 对其改写。

2、id = 1 为TABLE ACCESS FULL,表示CHAGENTBASE走的是全表扫描,在标量子查询中,主表返回多少
行,子表也跟着被扫描多少次,所以需要对CHAGENTBASE建索引。 3、SQL语句中出现TRIM(BILLNO) >= :B1 AND TRIM(BILLNO) <= :B2,导致ID = 16 为
INDEX FULL SCAN。对主键进行索引全扫描,这种访问方式是最垃圾的。

优化

1)创建索引
create indexIDX_CHAGENTBASE_TEST on CHAGENTBASE (AGENTCODE); 2)标量改成left join
select *
from (select G.*, rownum as num
from (SELECT A.BILLNO,
A.BILLCODE,
A.GETDATE,
A.GETUNITCODE,
A.GETCODE,
A.GETORGANCODE,
A.USEORGANCODE,
A.USEDATE,
A.USEUNITCODE,
A.USERCODE,
A.CURRENCYCODE,
A.AMOUNT,
A.NAME,
A.NOTES,
A.STATUSCODE,
A.IFPAGEONHOLE,
A.OPCODE,
A.OPUNITCODE,
A.OPDATE,
A.LOCKTIME,
A.GETAGENTCODE,
/* (SELECT D.AGENTNAME
FROM SYN_MM_AGENTCODE_TC D
WHERE D.AGENTCODE = A.GETAGENTCODE) AS GETAGENTNAME*/
D.AGENTNAME AS GETAGENTNAME,
A.USEAGENTCODE,
A.OUTSTATUS,
CASE A.BILLCODE
WHEN 'B2010005' THEN
A.FACTBILLCODE
ELSE
''
END FACTBILLCODE,
A.SALES,
A.FROMDATE,
A.TODATE,
/* (SELECT BILLNAME
FROM BD_BILLCODE
WHERE BILLCODE = A.BILLCODE) BILLNAME,*/
B.BILLNAME,
/* (SELECT HANDLERNAME
FROM BD_HANDLER
WHERE HANDLERCODE = A.USERCODE) USERNAME,*/
C.HANDLERNAME USERNAME,
/* (SELECT HANDLERNAME
FROM BD_HANDLER
WHERE HANDLERCODE = A.GETCODE) GETERNAME,*/
E.HANDLERNAME GETERNAME,
F.no3 ONLINEINVOICENO,
F.no4 ONLINEINVOICECODE
FROM B_BILL A
LEFT JOIN SYN_MM_AGENTCODE_TC D
ON D.AGENTCODE = A.GETAGENTCODE
LEFT JOIN BD_BILLCODE B
ON B.BILLCODE = A.BILLCODE
LEFT JOIN BD_HANDLER C
ON C.HANDLERCODE = A.USERCODE
LEFT JOIN BD_HANDLER E
ON E.HANDLERCODE = A.GETCODE
LEFT JOIN B_BILLDETAIL F
ON F.BILLNO = A.BILLNO
AND F.BILLCODE = A.BILLCODE
AND F.FACTBILLCODE = A.FACTBILLCODE
WHERE 3 > 2
AND 3 > 2
AND 3 > 2
AND 3 > 2
AND 3 > 2
AND trim(A.BILLNO) >= '601710100010'
AND trim(A.BILLNO) <= '601710100010'
AND 3 > 2
AND 3 > 2
AND 3 > 2
AND 3 > 2
AND 3 > 2
AND 3 > 2
ORDER BY A.BILLNO)G
where rownum <= 1)
where num > 0; Plan hash value: 1528527901 ------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 4632 | 21 (0)| 00:00:01 |
|* 1 | VIEW | | 1 | 4632 | 21 (0)| 00:00:01 |
|* 2 | COUNT STOPKEY | | | | | |
| 3 | VIEW | | 2 | 9238 | 21 (0)| 00:00:01 |
| 4 | NESTED LOOPS OUTER | | 2 | 832 | 21 (0)| 00:00:01 |
| 5 | NESTED LOOPS OUTER | | 2 | 770 | 19 (0)| 00:00:01 |
| 6 | NESTED LOOPS OUTER | | 2 | 718 | 17 (0)| 00:00:01 |
| 7 | NESTED LOOPS OUTER | | 2 | 614 | 12 (0)| 00:00:01 |
| 8 | NESTED LOOPS OUTER | | 2 | 562 | 10 (0)| 00:00:01 |
| 9 | TABLE ACCESS BY INDEX ROWID| B_BILL | 17395 | 3822K| 9 (0)| 00:00:01 |
|* 10 | INDEX FULL SCAN | PK_B_BILL_01 | 2 | | 8 (0)| 00:00:01 |
| 11 | TABLE ACCESS BY INDEX ROWID| CHAGENTBASE | 1 | 56 | 1 (0)| 00:00:01 |
|* 12 | INDEX RANGE SCAN | IDX_CHAGENTBASE_TEST | 1 | | 0 (0)| 00:00:01 |
| 13 | TABLE ACCESS BY INDEX ROWID | T_EMPLOYEE_VIEW | 1 | 26 | 2 (0)| 00:00:01 |
|* 14 | INDEX RANGE SCAN | IND_T_EMPLOYEE_VIEW | 1 | | 1 (0)| 00:00:01 |
| 15 | TABLE ACCESS BY INDEX ROWID | B_BILLDETAIL | 1 | 52 | 3 (0)| 00:00:01 |
|* 16 | INDEX RANGE SCAN | PK_B_BILLDETAIL_02 | 1 | | 2 (0)| 00:00:01 |
| 17 | TABLE ACCESS BY INDEX ROWID | T_EMPLOYEE_VIEW | 1 | 26 | 2 (0)| 00:00:01 |
|* 18 | INDEX RANGE SCAN | IND_T_EMPLOYEE_VIEW | 1 | | 1 (0)| 00:00:01 |
| 19 | TABLE ACCESS BY INDEX ROWID | BD_BILLCODE | 1 | 31 | 1 (0)| 00:00:01 |
|* 20 | INDEX UNIQUE SCAN | PK_BD_BILLCODE | 1 | | 0 (0)| 00:00:01 |
------------------------------------------------------------------------------------------------------------ Predicate Information (identified by operation id):
--------------------------------------------------- 1 - filter("NUM">0)
2 - filter(ROWNUM<=1)
10 - filter(TRIM("A"."BILLNO")>='601710100010' AND TRIM("A"."BILLNO")<='601710100010')
12 - access("D"."AGENTCODE"(+)="A"."GETAGENTCODE")
14 - access("A"."CODE"(+)="A"."GETCODE")
16 - access("F"."BILLNO"(+)="A"."BILLNO" AND "F"."BILLCODE"(+)="A"."BILLCODE" AND
"F"."FACTBILLCODE"(+)="A"."FACTBILLCODE")
18 - access("A"."CODE"(+)="A"."USERCODE")
20 - access("B"."BILLCODE"(+)="A"."BILLCODE") 3) 把Trim去掉 Execution Plan
----------------------------------------------------------
Plan hash value: 1229065410 ------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 4632 | 13 (0)| 00:00:01 |
|* 1 | VIEW | | 1 | 4632 | 13 (0)| 00:00:01 |
|* 2 | COUNT STOPKEY | | | | | |
| 3 | VIEW | | 1 | 4619 | 13 (0)| 00:00:01 |
| 4 | NESTED LOOPS OUTER | | 1 | 416 | 13 (0)| 00:00:01 |
| 5 | NESTED LOOPS OUTER | | 1 | 390 | 11 (0)| 00:00:01 |
| 6 | NESTED LOOPS OUTER | | 1 | 364 | 9 (0)| 00:00:01 |
| 7 | NESTED LOOPS OUTER | | 1 | 308 | 8 (0)| 00:00:01 |
| 8 | NESTED LOOPS OUTER | | 1 | 277 | 7 (0)| 00:00:01 |
| 9 | TABLE ACCESS BY INDEX ROWID| B_BILL | 1 | 225 | 4 (0)| 00:00:01 |
|* 10 | INDEX RANGE SCAN | PK_B_BILL | 1 | | 3 (0)| 00:00:01 |
| 11 | TABLE ACCESS BY INDEX ROWID| B_BILLDETAIL | 1 | 52 | 3 (0)| 00:00:01 |
|* 12 | INDEX RANGE SCAN | PK_B_BILLDETAIL_02 | 1 | | 2 (0)| 00:00:01 |
| 13 | TABLE ACCESS BY INDEX ROWID | BD_BILLCODE | 1 | 31 | 1 (0)| 00:00:01 |
|* 14 | INDEX UNIQUE SCAN | PK_BD_BILLCODE | 1 | | 0 (0)| 00:00:01 |
| 15 | TABLE ACCESS BY INDEX ROWID | CHAGENTBASE | 1 | 56 | 1 (0)| 00:00:01 |
|* 16 | INDEX RANGE SCAN | IDX_CHAGENTBASE_TEST | 1 | | 0 (0)| 00:00:01 |
| 17 | TABLE ACCESS BY INDEX ROWID | T_EMPLOYEE_VIEW | 1 | 26 | 2 (0)| 00:00:01 |
|* 18 | INDEX RANGE SCAN | IND_T_EMPLOYEE_VIEW | 1 | | 1 (0)| 00:00:01 |
| 19 | TABLE ACCESS BY INDEX ROWID | T_EMPLOYEE_VIEW | 1 | 26 | 2 (0)| 00:00:01 |
|* 20 | INDEX RANGE SCAN | IND_T_EMPLOYEE_VIEW | 1 | | 1 (0)| 00:00:01 |
------------------------------------------------------------------------------------------------------------ Predicate Information (identified by operation id):
--------------------------------------------------- 1 - filter("NUM">0)
2 - filter(ROWNUM<=1)
10 - access("A"."BILLNO"='601710100010')
12 - access("F"."BILLNO"(+)='601710100010' AND "F"."BILLCODE"(+)="A"."BILLCODE" AND
"F"."FACTBILLCODE"(+)="A"."FACTBILLCODE")
filter("F"."BILLNO"(+)="A"."BILLNO")
14 - access("B"."BILLCODE"(+)="A"."BILLCODE")
16 - access("D"."AGENTCODE"(+)="A"."GETAGENTCODE")
18 - access("A"."CODE"(+)="A"."GETCODE")
20 - access("A"."CODE"(+)="A"."USERCODE") Statistics
----------------------------------------------------------
621 recursive calls
0 db block gets
229 consistent gets
17 physical reads
0 redo size
2937 bytes sent via SQL*Net to client
2086 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
16 sorts (memory)
0 sorts (disk)
1 rows processed

优化效果

可以看出消耗的 buffer cache 从之前的882,856,212.00 降到了229,效率提升了N倍.

又是latch: cache buffers chains惹得祸的更多相关文章

  1. 【转载】latch: cache buffers chains

    本文转自惜分飞的博客,博客原文地址:www.xifenfei.com/1109.html,支持原创,分享知识! 当一个数据块读入sga区,相应的buffer header会被放置到hash列表上,我们 ...

  2. Oracle索引失效问题:WHERE C1='' OR C2 IN(SubQuery),并发请求时出现大量latch: cache buffers chains等待

    问题描述: 项目反馈某功能响应时间很长,高峰期时系统整体响应很慢... 获取相应的AWR,问题确实比较严重,latch: cache buffers chains等待,因为这些会话SQL执行时间太长, ...

  3. latch: cache buffers chains故障处理总结(转载)

    一大早就接到开发商的电话,说数据库的CPU使用率为100%,应用相应迟缓.急匆匆的赶到现场发现进行了基本的检查后发现是latch: cache buffers chains 作祟,处理过程还算顺利,当 ...

  4. 案例:latch: cache buffers chains event tuning

    前两天对oracle数据库(single instance)进行了迁移升级从10.2.0.4 升到11.2.0.3,有一个项目迁完后第二天,cpu负载升到了130更高(16cpus). 向用户询问后使 ...

  5. latch: cache buffers chains故障处理总结

    一大早就接到开发商的电话,说数据库的CPU使用率为100%,应用相应迟缓.急匆匆的赶到现场发现进行了基本的检查后发现是latch: cache buffers chains 作祟,处理过程还算顺利,当 ...

  6. 关于latch: cache buffers chains的sql优化

    前段时间,优化了一些耗buffer比较多的sql,但是CPU使用率还是没下来 . 查看操作系统CPU使用率 查看awr,发现又有一条超级耗性能的sql冒出来了. 该SQL每次执行耗费3e多个buffe ...

  7. [转帖]深入理解latch: cache buffers chains

    深入理解latch: cache buffers chains http://blog.itpub.net/12679300/viewspace-1244578/ 原创 Oracle 作者:wzq60 ...

  8. latch:cache buffers chains的优化思路

    数据块在buffer cache存放是以linked list方式存放的.当一个session想要访问/修改buffer cache的block,首先需要通过hash算法检查该block是否存在于bu ...

  9. cache buffers chains latch

    cache buffers chains latch 从 Oracle 8i Database 开始, 散列锁存器<-------(1:m)------>hash bucket<-- ...

随机推荐

  1. E20170517-gg

    jaw  n. 下巴; 颌; indicator n. 指示器; gator  n. 短吻鳄; median  n. 中位数; 中线; [数] 中值;

  2. python 面向对象二 类和实例

    一.类和实例 面向对象最重要的概念就是类(Class)和实例(Instance),必须牢记类是抽象的模板,比如Student类,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法, ...

  3. hdu 3007【最小圆覆盖-随机增量法模板】

    #include<iostream> #include<cstdio> #include<cmath> #include<algorithm> usin ...

  4. 洛谷 P4013 数字梯形问题【最大费用最大流】

    第一问:因为每个点只能经过一次,所以拆点限制流量,建(i,i',1,val[i]),然后s向第一行建(s,i,1,0),表示每个点只能出发一次,然后最后一行连向汇点(i',t,1,0),跑最大费用最大 ...

  5. UVA - 10859 Placing Lampposts 放置街灯

    Placing Lampposts 传送门:https://vjudge.net/problem/UVA-10859 题目大意:给你一片森林,要求你在一些节点上放上灯,一个点放灯能照亮与之相连的所有的 ...

  6. bzoj1415 [Noi2005]聪聪和可可【概率dp 数学期望】

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1415 noip2016 D1T3,多么痛的领悟...看来要恶补一下与期望相关的东西了. 这是 ...

  7. 加密解密(1)HTTPS与HTTP区别

    HTTPS简介 HTTPS(全称:Hypertext Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版.即 ...

  8. 移动端rem单位用法

    1.rem(font size of the root element)是指相对于根元素的字体大小的单位,em(font size of the element)是指相对于父元素的字体大小的单位.它们 ...

  9. OAuth 开放授权 Open Authorization

    http://oauth.net/ http://tools.ietf.org/html/rfc6749 http://reg.163.com/help/help_oauth2.html 网易通行证O ...

  10. 把List<Map<String,Object>>转成Map<String,Object>

    Map<String, Object> parmMap = new HashMap<String, Object>(); //定义一个用于存储强转后的Map List<M ...