latch: cache buffers chains引起的响应慢
来源:互联网 发布:算法工程师招聘 编辑:程序博客网 时间:2024/05/16 09:28
今天凌晨升级了SP接口的应用代码,下午SP联调测试时,发现没有返回响应包,超过约定的500ms。查询后台日志,发现响应基本在22s左右,难怪他们反映说没响应。应用还未正式上线,所以不可能是并发应用的数据库争用引起的,排除运维人员查询和统计之后,登录数据库查询。
SELECT event,COUNT (1) from v$session_wait GROUP BY event ORDER BY COUNT(1 ) DESC;
发现偶尔存在latch: cache buffers chains等待事件,根据该事件(脚本太长,就不贴出来了),查询发现时如下语句造成的。
SELECT *
FROM TB_BM_PROD_INST INST
WHERE PROD_TYPE_CD = 'SP_NAME'
AND (INST.PRODUCT_ID = 47 AND
INST.SERV_CODE IN
( SELECT SERV_CODE FROM TB_BM_QOS_CUST WHERE DIAL_ACCT IN (:1 )) OR
INST.CUST_ID IN
( SELECT CUST_ID FROM TB_BM_SP_CUST WHERE SP_ACCOUNT IN (:2 )))
这确实是由于局方需求,修改了SQL逻辑,之前在开发库,相应的索引都已经建了的,看下生产库,是否有建。
SQL> SELECT IND.TABLE_NAME, IND.INDEX_NAME, COL.COLUMN_NAME, STATUS
2 FROM USER_INDEXES IND, USER_IND_COLUMNS COL
3 WHERE IND.INDEX_NAME = COL.INDEX_NAME
4 AND IND.TABLE_NAME IN
5 ('TB_BM_PROD_INST', 'TB_BM_QOS_CUST', 'TB_BM_SP_CUST')
6 ORDER BY IND.TABLE_NAME, COL.COLUMN_NAME;
TABLE_NAME INDEX_NAME COLUMN_NAME STATUS
------------------------------ ------------------------------ ------------------------------ --------
TB_BM_PROD_INST INX_PROD_INST_CREATE_DATE CREATE_DATE VALID
TB_BM_PROD_INST IX_PROD_INST_CUST_ID CUST_ID VALID
TB_BM_PROD_INST AK_KEY_1_TB_BM_PR PROD_INST_ID VALID
TB_BM_PROD_INST INDEX_SERV_CODE SERV_CODE VALID
TB_BM_QOS_CUST INDEX_ACC_NBR ACC_NBR VALID
TB_BM_QOS_CUST PK_TB_BM_QOS_CUST CUST_ID VALID
TB_BM_QOS_CUST INDEX_DIAL_ACCT DIAL_ACCT VALID
TB_BM_QOS_CUST INX_QOS_CUST_OPEN_DATE OPEN_DATE VALID
TB_BM_QOS_CUST INX_CUST_SERV_CODE SERV_CODE VALID
TB_BM_SP_CUST SYS_C0010423 CUST_ID VALID
TB_BM_SP_CUST INX_SP_ACCOUONT SP_ACCOUNT VALID
11 rows selected
查询目前的执行计划:
SQL> explain plan for
2
2 SELECT *
3 FROM TB_BM_PROD_INST INST
4 WHERE PROD_TYPE_CD = 'SP_NAME'
5 AND (INST.PRODUCT_ID = 47 AND
6 INST.SERV_CODE IN
7 ( SELECT SERV_CODE FROM TB_BM_QOS_CUST WHERE DIAL_ACCT IN (:1 )) OR
8 INST.CUST_ID IN
9 ( SELECT CUST_ID FROM TB_BM_SP_CUST WHERE SP_ACCOUNT IN (:2 )))
10 ;
Explained
SQL> select * from table(DBMS_XPLAN.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1748848417
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 32792 | 2754K| 166
|* 1 | FILTER | | | |
|* 2 | TABLE ACCESS FULL | TB_BM_PROD_INST | 381K| 31M| 166
|* 3 | TABLE ACCESS BY INDEX ROWID| TB_BM_SP_CUST | 1 | 14 |
|* 4 | INDEX RANGE SCAN | INX_SP_ACCOUONT | 1 | |
|* 5 | TABLE ACCESS BY INDEX ROWID| TB_BM_QOS_CUST | 1 | 39 |
|* 6 | INDEX RANGE SCAN | INX_CUST_SERV_CODE | 1 | |
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter( EXISTS (SELECT 0 FROM "TB_BM_SP_CUST" "TB_BM_SP_CUST" WHERE "SP_A
AND "CUST_ID"=:B1) OR "INST"."PRODUCT_ID"=47 AND EXISTS (SELECT 0
"TB_BM_QOS_CUST" WHERE "SERV_CODE"=:B2 AND "DIAL_ACCT"=:1))
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
2 - filter("PROD_TYPE_CD"='SP_NAME')
3 - filter("CUST_ID"=:B1)
4 - access("SP_ACCOUNT"=:2)
5 - filter("DIAL_ACCT"=:1)
6 - access("SERV_CODE"=:B1)
25 rows selected
可以发现,OR IN 操作已经转换成AND EXISTS;第2步中,通过"PROD_TYPE_CD"='SP_NAME'过滤后,再和第3和第5步的结果集做全表扫描的FILTER。
优化思路:
既然索引都存在,就尽量使用索引,OR操作可以使用UNION替换,本例用UNION ALL,因为两段逻辑不可能同时成立。
SELECT *
FROM TB_BM_PROD_INST INST
WHERE PROD_TYPE_CD = 'SP_NAME'
AND (INST.PRODUCT_ID = 47 AND
INST.SERV_CODE IN
( SELECT SERV_CODE FROM TB_BM_QOS_CUST WHERE DIAL_ACCT IN (:1 )))
UNION ALL
SELECT *
FROM TB_BM_PROD_INST INST
WHERE INST.CUST_ID IN
( SELECT CUST_ID FROM TB_BM_SP_CUST WHERE SP_ACCOUNT IN (:2 ))
AND (PRODUCT_ID = : 3)
查看执行计划:
SQL> explain plan for
2
2 SELECT *
3 FROM TB_BM_PROD_INST INST
4 WHERE PROD_TYPE_CD = 'SP_NAME'
5 AND (INST.PRODUCT_ID = 47 AND
6 INST.SERV_CODE IN
7 (SELECT SERV_CODE FROM TB_BM_QOS_CUST WHERE DIAL_ACCT IN (:1)))
8 UNION ALL
9 SELECT *
10 FROM TB_BM_PROD_INST INST
11 WHERE INST.CUST_ID IN
12 (SELECT CUST_ID FROM TB_BM_SP_CUST WHERE SP_ACCOUNT IN (:2))
13 AND (PRODUCT_ID = :3)
14 ;
Explained
SQL> select * from table(DBMS_XPLAN.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2953549902
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 225 |
| 1 | UNION-ALL | | | |
| 2 | NESTED LOOPS | | | |
| 3 | NESTED LOOPS | | 1 | 125 |
| 4 | SORT UNIQUE | | 1 | 39 |
| 5 | TABLE ACCESS BY INDEX ROWID| TB_BM_QOS_CUST | 1 | 39 |
|* 6 | INDEX RANGE SCAN | INDEX_DIAL_ACCT | 1 | |
|* 7 | INDEX RANGE SCAN | INDEX_SERV_CODE | 1 | |
|* 8 | TABLE ACCESS BY INDEX ROWID | TB_BM_PROD_INST | 1 | 86 |
| 9 | NESTED LOOPS | | | |
| 10 | NESTED LOOPS | | 1 | 100 |
| 11 | SORT UNIQUE | | 1 | 14 |
| 12 | TABLE ACCESS BY INDEX ROWID| TB_BM_SP_CUST | 1 | 14 |
|* 13 | INDEX RANGE SCAN | INX_SP_ACCOUONT | 1 | |
|* 14 | INDEX RANGE SCAN | IX_PROD_INST_CUST_ID | 3 | |
|* 15 | TABLE ACCESS BY INDEX ROWID | TB_BM_PROD_INST | 1 | 86 |
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
6 - access("DIAL_ACCT"=:1)
7 - access("INST"."SERV_CODE"="SERV_CODE")
8 - filter("INST"."PRODUCT_ID"=47 AND "PROD_TYPE_CD"='SP_NAME')
13 - access("SP_ACCOUNT"=:2)
14 - access("INST"."CUST_ID"="CUST_ID")
15 - filter("PRODUCT_ID"=TO_NUMBER(:3))
32 rows selected
发现所有的索引都用到,而且是NL连接.
比对前后的Bytes,由原来2754K降为225。
再次找SP厂家确认后,响应很快,监控后台的等待事件,没发现异常。
- latch: cache buffers chains引起的响应慢
- latch: cache buffers chains
- latch: cache buffers chains
- latch: cache buffers chains
- latch: cache buffers chains
- latch: cache buffers chains
- cache buffers chains latch
- latch: cache buffers chains
- latch:cache buffers chains的优化思路
- 缓解latch: cache buffers chains的案例
- Cache buffers chains latch 与Cache buffers LRU chain latch
- 低效的SQL引发的cache buffers chains latch
- latch: cache buffers chains-热块的简单模拟实验
- 一个cache buffers chains latch需要管理的块
- latch: cache buffers chains导致CPU冲高的问题
- 关于latch: cache buffers chains的sql优化
- Cache Buffers Chains and Latch Spelunking
- latch:cache buffers chains等待问题
- Word-frequency filter
- 350 - Pseudo-Random Numbers
- 常用正则表达式整理
- Oracle 聚合函数解决聚集连接字符串问题
- Linux驱动阻塞的实现
- latch: cache buffers chains引起的响应慢
- 黑马程序员-泛型
- 最简单的存储过程写法及调用
- Struts2、SpringMVC、Servlet(Jsp)性能对比 测试
- 黄淮学院CSDN高校俱乐部项目开发之小区车辆智能识别系统
- 手动修改Android数据库数据
- Android多媒体学习十三:检索MediaStore中的Video和其对应的缩略图信息
- Dom4j中的中文编码问题
- HDU--1049 -- Climbing Worm