前言

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

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. RTSP协议简介(转载)

    转自:http://ilinux.iteye.com/blog/505753 Real Time Streaming Protocol 或 者RTSP(实时流媒体协议),是由Real network ...

  2. bzoj 3751: [NOIP2014]解方程【数学】

    --我真是太非了,自己搞了7个质数都WA,从别人那粘5个质数就A了-- 就是直接枚举解,用裴蜀定理计算是否符合要求,因为这里显然结果很大,所以我们对多个质数取模看最后是不是都为0 #include&l ...

  3. P5106 dkw的lcm

    传送门 终于A了--细节真多-- 首先我们发现这是个连乘,而且\(\phi\)是个积性函数,所以我们可以考虑不同的质因子以及它的不同次数的贡献.简单来说就是把每一次的\(\phi(lcm(i_1,i_ ...

  4. P4357 [CQOI2016]K远点对(KDTree)

    传送门 又一次产生了KDTree本质就是爆搜的感觉-- 大概就类似于p4169,只不过是从最近点对变成了第\(k\)远点对 我们开一个小根堆,里面放\(k\)个元素,起初全为\(0\),然后每一次都把 ...

  5. 一条SQL语句是如何执行的?--Mysql45讲笔记记录 打卡day1

    写在前面的话:回想以前上班的时候,空闲时间还是挺多的,但是都荒废了.如今找工作着实费劲了.但是这段时间在极客时间买了mysql45讲,就好像发现了新大陆一样,这是我认真做笔记的第一天,说实话第一讲我已 ...

  6. 压力测试之jmeter使用

    我很早之前就会使用jmeter,一直以为压力测试很简单,知道真正去做才明白,真正的压力测试并不只是会用jmeter而已.我现在才明白:会工具并不等同于会压力测试.对于压力测试需要补充的知识还有很多.. ...

  7. 进击的Python【第十五章】:Web前端基础之DOM

    进击的Python[第十五章]:Web前端基础之DOM 简介:文档对象模型(Document Object Model,DOM)是一种用于HTML和XML文档的编程接口.它给文档提供了一种结构化的表示 ...

  8. [IOI1998]Picture

    Description 在一个平面上放置一些矩形,所有的边都为垂直或水平.每个矩形可以被其它矩形部分或完全遮盖,所有矩形合并成区域的边界周长称为轮廓周长. 要求:计算轮廓周长. 数据规模: 0≤矩形数 ...

  9. poj 1664 放苹果 递归

    题目链接: http://poj.org/problem?id=1664 题目描述: 有n个苹果,m个盒子,盒子和苹果都没有顺序,盒子可以为空,问:有多少种放置方式? 解题思路: 当前有n个苹果,m个 ...

  10. jmeter(七)函数

    JMeter函数是一些能够转化在测试树中取样器或者其他配置元件的域的特殊值.一个函数的调用就像这样:${_functionName(var1,var2,var3)},-functionName匹配函数 ...