日期:2014-05-16  浏览次数:20952 次

索引已有,索引统计信息已统计,返回行数不多,但就不走索引扫描?
请帮帮忙,问题索引已建,但不走索引?
SQL如下:
SELECT * 
FROM CP_SMS_PHONE_NUMBER csp
WHERE csp.phone_no like '138'||'%';
目前,phone_no字段上也有索引,在A库上执行能走索引,然后需要把A库的表导出到B库,B库上再执行相同的语句就不走索引了。

具体执行计划
A库中得执行计划
--------------------------------------------

-------------------

| Id  | Operation                   | Name                | Rows  | Bytes | Cost

 (%CPU)| Time     |

--------------------------------------------

-------------------

|   0 | SELECT STATEMENT            |                     |     2 |   172 |
4   (0)| 00:00:01 |

|   1 |  TABLE ACCESS BY INDEX ROWID| CP_SMS_PHONE_NUMBER |     2 |   172 |
4   (0)| 00:00:01 |

|*  2 |   INDEX RANGE SCAN          | IDX_PHONENO         |     2 |       |
2   (0)| 00:00:01 |

--------------------------------------------


B库中得执行计划
| Id  | Operation         | Name                | Rows  | Bytes | Cost (%CPU)| T

ime     |

--------------------------------------------

---------

|   0 | SELECT STATEMENT  |                     |   262 | 22270 |     6   (0)| 0

0:00:01 |

|*  1 |  TABLE ACCESS FULL| CP_SMS_PHONE_NUMBER |   262 | 22270 |     6   (0)| 0

0:00:01 |

--------------------------------------------

------解决方案--------------------
你对导入到B库的表做了数据采集了吗?
如果没有的话,做下数据采集在试。

还有你两个库相同的查询语句,返回的数据怎么不一样
------解决方案--------------------
Oracle使用索引的机制是这样的:在数据条数比较少的情况下,很可能是不走索引的。这是由Oracle的索引原理决定的。因为使用索引查询时,首先是要读取索引块,然后通过索引块得到rowid,然后根据这个rowid定位到数据块的位置,然后从数据块中读取数据(中间还要读取slot,这里不用考虑这么细)。因此这样至少要读入两个块进Oracle的SGA。虽然你这里统计了,可以Oracle会自动优化,根据统计信息,Oracle认为全表扫描效率更好,因此就不走索引。所以说,全表扫描到底好不好,使用索引查询到底好不好是要辩证着看,建议楼主如果有兴趣,可以深入研究下索引的机制。希望说的,能帮上楼主,继续交流,呵呵呵。
------解决方案--------------------
分析一下B库这个表

 dbms_stats.gather_table_stats(user,table_name);
------解决方案--------------------
achilles12345
说的很有道理啊,我也觉得可能oracle觉得做全表扫描代价更小,但最大的问题是为什么我在A库中执行同样的语句时就能用到索引呢?另外,在B库我已经dbms_stats.gather_table_stats(user,table_name);和dbms_stats.gather_index_stats(user,index_name);了?