代码改变世界

案例编号 0005---index range scan, index full scan, out-of_date statistics

2011-09-02 15:53  Tracy.  阅读(438)  评论(0编辑  收藏  举报

案例编号: 0005
关键词: index range scan, index full scan, out-of_date statistics
正文:

出问题的SQL:
SELECT *
FROM ZORYZYZ.VD_TLOWVM_KSLGL
WHERE member_id = :1
AND status IN (:2)
ORDER BY member_id, id

当前的执行计划(index full scan):
-----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
-----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 666 | 1 |
|* 1 | TABLE ACCESS BY INDEX ROWID| VD_TLOWVM_KSLGL | 1 | 666 | 1 |
| 2 | INDEX FULL SCAN | VD_TLOWVM_KSLGL_KP | 1 | | |
-----------------------------------------------------------------------------------

希望它走的执行计划(index range scan):
-----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 64 | 19 |
| 1 | SORT ORDER BY | | 1 | 64 | 19 |
|* 2 | TABLE ACCESS BY INDEX ROWID| VD_TLOWVM_KSLGL | 1 | 64 | 3 |
|* 3 | INDEX RANGE SCAN | VD_TLOWVM_KSLGL_NRW_RMW | 14 | | 1 |
-----------------------------------------------------------------------------------------

原因是索引全扫描的成本被明显的低估了, 经检查, 原来是表统计信息和索引统计信息失真:

现在的统计信息:

INDEX_NAME LEAF_BLOCKS LAST_ANALYZED
----------------------------------- ----------- -------------------
VD_TLOWVM_KSLGL_KP 0 2008-08-25 13:35:13
VD_TLOWVM_KSLGL_NRW_RMW 0 2008-08-25 13:35:13

TABLE_NAME NUM_ROWS BLOCKS LAST_ANALYZED
------------------------------ ---------- ---------- -------------------
VD_TLOWVM_KSLGL 0 0 2008-08-25 13:35:13


ANALYZE TABLE VD_TLOWVM_KSLGL estimate STATISTICS FOR TABLE FOR ALL INDEXES;
重新收集统计信息以后
--------------------------------------------------------------------------------------------------
统计信息:
INDEX_NAME LEAF_BLOCKS LAST_ANALYZED
----------------------------------- ----------- -------------------
VD_TLOWVM_KSLGL_KP 10 2008-09-01 14:33:40
VD_TLOWVM_KSLGL_NRW_RMW 15 2008-09-01 14:33:40

TABLE_NAME NUM_ROWS BLOCKS LAST_ANALYZED
------------------------------ ---------- ---------- -------------------
VD_TLOWVM_KSLGL 3518 60 2008-09-01 14:33:40


执行计划:
-----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 64 | 19 |
| 1 | SORT ORDER BY | | 1 | 64 | 19 |
|* 2 | TABLE ACCESS BY INDEX ROWID| VD_TLOWVM_KSLGL | 1 | 64 | 3 |
|* 3 | INDEX RANGE SCAN | VD_TLOWVM_KSLGL_NRW_RMW | 14 | | 1 |
-----------------------------------------------------------------------------------------

对比此时的索引全扫描成本:
-----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
-----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 64 | 2685 |
|* 1 | TABLE ACCESS BY INDEX ROWID| VD_TLOWVM_KSLGL | 1 | 64 | 2685 |
| 2 | INDEX FULL SCAN | VD_TLOWVM_KSLGL_KP | 3518 | | 11 |
-----------------------------------------------------------------------------------


前后比较可以看到, INDEX FULL SCAN(VD_TLOWVM_KSLGL_KP)回表的真实成本是 2685,
而当统计信息缺失时, 这个成本被误算为 1, 导致CBO错误的选择了它作为执行计划.


用到的公式:
索引全扫描成本:
Cost = dba_indexes.leaf_blocks / db_file_multiblock_read_count * x
这个x是每个数据库的system统计信息决定的, 在一个指定的数据库中, 这个值是恒定的.

 

引自:http://space.itpub.net/206723/viewspace-474781