今天具体开发的同事提出这样一个问题
SQL> set autotrace traceonly explain
SQL> select * from xxx where aac001 = '111';
Execution Plan
----------------------------------------------------------
---------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
---------------------------------------------------------------
| 0 | SELECT STATEMENT | | 55 | 22275 | 3 (0)|
| 1 | TABLE ACCESS FULL| xxx | 55 | 22275 | 3 (0)|
---------------------------------------------------------------
Note
-----
在xxx.aac001上是存在索引的,但为什么不走索引呢?
接到这个问题,首先排除该索引是否失效了
SQL> select index_name,status from user_indexes where index_name = 'IDX_XXX_AAC
001';
INDEX_NAME STATUS
------------------------------ --------
IDX_XXX_AAC001 VALID
答案是否定的。接着对表和索引进行了分析
analyze index idx_xxx_aac001 validate structure;
analyze table xxx delete statistics;
analyze table xxx compute statistics;
仍然是全表扫描,奇怪了,隐式转换不可能,开发人员还不至于犯如此错误
因为是开发库,数量变化可能没有规律,所以重新rebuild一下索引吧
SQL> set autotrace traceonly explain
SQL> select * from xxx where aac001 = '111';
Execution Plan
----------------------------------------------------------
---------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
---------------------------------------------------------------
| 0 | SELECT STATEMENT | | 65 | 26260 | 3 (0)|
| 1 | TABLE ACCESS FULL| xxx | 65 | 26260 | 3 (0)|
---------------------------------------------------------------
Note
-----
- 'PLAN_TABLE' is old version
SQL>
没有起作用
不是组合索引,该列也不可能为空,那是什么原因呢
SQL> select count(*) from xxx;
COUNT(*)
----------
68
SQL> select count(*) from xxx where aac001 = '111';
COUNT(*)
----------
65
换个人试一下
SQL> explain plan for select * from xxx where aac001 = '123';
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
----
| Id | Operation | Name | Rows | Bytes | Cost (%C
PU)|
--------------------------------------------------------------------------------
----
| 0 | SELECT STATEMENT | | 1 | 404 | 2
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
(0)|
| 1 | TABLE ACCESS BY INDEX ROWID| xxx | 1 | 404 | 2
(0)|
| 2 | INDEX RANGE SCAN | IDX_xxx_AAC001 | 1 | | 1
(0)|
--------------------------------------------------------------------------------
----
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Note
-----
- 'PLAN_TABLE' is old version
12 rows selected.
答案出来了,就是这个问题,由于是开发库,没有真实的数据,所有数据均为开发人员手动造的,辛苦了
以前总是在说,基于COST优化:表数据量小,全表扫描比走索引效率高
很简单,你的表数据可能占用一个块,索引也是占用一个块,
如果全表扫描,只需读一个块,而使用索引则要读两个块,
显然使用索引成本更高,因此oracle决定使用全表扫描。
但真的碰到了,还是很难想到。通过这次,oracle优化器的智慧让我折服了,对其印象更加深刻了,并不是所有情况使用索引都会加快查询速度,full scan table 有时会更快,尤其是当查询的数据量占整个表的比重较大时。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/13726712/viewspace-680555/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/13726712/viewspace-680555/