
开发人员在进行新系统上线前的数据校验测试时,发现一条手工执行的SQL执行了超过1小时还没有返回结果。SQL很简单:
SELECT *
FROM MOBILE_call_1204_OLD
WHERE BILLING_NBR = '189xxxxxxxx'
AND START_DATE = TO_DATE('2012-4-9 21:55:42', 'yyyy-mm-dd hh24:mi:ss')
下面是这条SQL的真实的执行计划:
-------------------------------------------------------------
| Id | Operation | Name | E-Rows |
-------------------------------------------------------------
| 0 | SELECT STATEMENT | | |
| * 1 | TABLE ACCESS FULL | MOBILE_CALL_1204_OLD | 1 |
-------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(("START_DATE"=TO_DATE(' 2012-04-09 21:55:42', 'syyyy-mm-dd hh24:mi:ss') AND "BILLING_NBR"='189xxxxxxxx'))
很显然,在这个表上建billing_nbr和start_date的复合索引,这条SQL就能很快执行完(实际上最后也建了索引)。但是这里我们要探讨的是,为什么这么一条简单的SQL语句,执行了超过1小时还没有结果。MOBILE_CALL_1204_OLD这张表的大小约为12GB,以系统的IO能力,正常情况下不会执行这么长的时间。简单地看了一下,系统的CPU以及IO压力都不高。假设单进程全表扫描表,每秒扫描50MB大小(这实际上是一个很保守的扫描速度了),那么只需要245秒就可以完成扫描。
下面来诊断一下SQL为什么会这么不正常地慢。看看会话的等待(以下会用到Oracle大牛Tanel Poder的脚本):
SQL> @waitprof print 4038 e 1000000
Distinct Avg time
SID STATE EVENT Time Time ms Events ms/Event
------- ------- ------------------------- ------- ------------ ---------- ----------
4038 WAITING db file sequential read 99.61 4482.450 272 16.480
4038 WORKING On CPU / runqueue .39 17.550 271 .065
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-30053-1.html
将来
快要过生日啦
向第一财经致敬