索引已有,索引统计信息已统计,返回行数不多,但就不走索引扫描?
请帮帮忙,问题索引已建,但不走索引?
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);了?