日历

2008 7.6 Sun
  12345
6789101112
13141516171819
20212223242526
2728293031  
«» 2008 - 7 «»

文章搜索

日志文章

2008年04月24日 19:54:49

一次简单的SQL tuning

发现应用程序慢,开始把目光放在检查商业逻辑的SQL上面,觉得没什么问题,但是执行时间大大超出我的预期。
后来询问开发人员,原来最初会取工单表里面的最近工单时间,最早工单时间来做对比。
根据经验,对索引字段做MAX或者MIN是很快的,因为索引是有序,优化器直接到索引头或者尾部去取rowid就可以了。
但是打开程序一看,SQLpreparement里面的句子是这样的:
select min(billtime),MAX(billtime) from billcontent
觉得有问题了,一看执行计划,恍然大悟:
Execution Plan
----------------------------------------------------------
Plan hash value: 1499044795
-----------------------------------------------------------------------------------------------------------------
| Id | Operation           | Name             | Rows | Bytes | Cost (%CPU)| Time   | Pstart| Pstop |
-----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |               |   1 |   8 | 5126   (3)| 00:01:02 |     |     |
|   1 | SORT AGGREGATE       |               |   1 |   8 |         |       |     |     |
|   2 |   PARTITION RANGE SINGLE|               | 7653K|   58M| 5126   (3)| 00:01:02 |   1 |   1 |
|   3 |   PARTITION LIST ALL   |               | 7653K|   58M| 5126   (3)| 00:01:02 |   1 |   21 |
|   4 |   INDEX FAST FULL SCAN| IDX_ANALYSE_CONTENT_2 | 7653K|   58M| 5126   (3)| 00:01:02 |   1 |   21 |
-----------------------------------------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
    26745 consistent gets
是INDEX FAST FULL SCAN,26745 个一致读,5126 的Cost,大概查了一下,该索引拥有27632个块,现在对索引做了完全扫描。
对于一致读和Cost的计算方法,这里暂不多述。
只查一个极限值话:
select min(billtime) from billcontent;
Execution Plan
----------------------------------------------------------
Plan hash value: 4137395070
----------------------------------------------------------------------------------------------------------------------
| Id | Operation             | Name             | Rows | Bytes | Cost (%CPU)| Time   | Pstart| Pstop |
----------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT         |               |   1 |   8 |   3   (0)| 00:00:01 |     |     |
|   1 | SORT AGGREGATE         |               |   1 |   8 |         |       |     |     |
|   2 |   PARTITION RANGE SINGLE   |               | 7653K|   58M|   3   (0)| 00:00:01 |   1 |   1 |
|   3 |   PARTITION LIST ALL     |               | 7653K|   58M|   3   (0)| 00:00:01 |   1 |   21 |
|   4 |   INDEX FULL SCAN (MIN/MAX)| IDX_ANALYSE_CONTENT_2 | 7653K|   58M|   3   (0)| 00:00:01 |   1 |   21 |
----------------------------------------------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
      42 consistent gets
计划是INDEX FULL SCAN (MIN/MAX),(MIN/MAX)表明只会访问索引的头或尾,开销大大减小,只有42个一致读和极低的Cost,正常情况只能是
这个的两倍多。
马上动手改为
SELECT
(select min(calltime) from analyse_content ),
(select MAX(calltime) from analyse_content )
FROM dual
Execution Plan
----------------------------------------------------------
Plan hash value: 2326664376
----------------------------------------------------------------------------------------------------------------------
| Id | Operation             | Name             | Rows | Bytes | Cost (%CPU)| Time   | Pstart| Pstop |
----------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT         |               |   1 |     |   2   (0)| 00:00:01 |     |     |
|   1 | SORT AGGREGATE         |               |   1 |   8 |         |       |     |     |
|   2 |   PARTITION RANGE SINGLE   |               | 7653K|   58M|   3   (0)| 00:00:01 |   1 |   1 |
|   3 |   PARTITION LIST ALL     |               | 7653K|   58M|   3   (0)| 00:00:01 |   1 |   21 |
|   4 |   INDEX FULL SCAN (MIN/MAX)| IDX_ANALYSE_CONTENT_2 | 7653K|   58M|   3   (0)| 00:00:01 |   1 |   21 |
|   5 | SORT AGGREGATE         |               |   1 |   8 |         |       |     |     |
|   6 |   PARTITION RANGE SINGLE   |               | 7653K|   58M|   3   (0)| 00:00:01 |   1 |   1 |
|   7 |   PARTITION LIST ALL     |               | 7653K|   58M|   3   (0)| 00:00:01 |   1 |   21 |
|   8 |   INDEX FULL SCAN (MIN/MAX)| IDX_ANALYSE_CONTENT_2 | 7653K|   58M|   3   (0)| 00:00:01 |   1 |   21 |
|   9 | FAST DUAL             |               |   1 |     |   2   (0)| 00:00:01 |     |     |
----------------------------------------------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
      84 consistent gets
完美解决。
总结:
其实这个问题很小,这个SQL人人都会写,但是很多开发人员,在写这种SQL的时候不会去思考结果产生的过程,以实现为原则,在他们眼中数
据库仍然是黑盒。在测试过程中也没有仔细观察效率,在测试表数据较少,人眼感觉不出来问题,一在生产库跑就越来越慢。
所以,无论是开发和DBA多学习数据库的执行机制和原理,是没有害处的。

Tags: tuning  

类别: Tuning |  评论(0) |  浏览(2232) |  收藏
发表评论