2008年12月7日星期日

ORACLE使用索引的一个小问题

其实从9i以后ORACLE就一直使用CBO,如果说ORACLE要使用索引的话,只有两个条件:

一,查询过滤条件所在字段上有索引

二,使用索引扫描的成本低于表扫描成本

前两天有人举例子讲ORACLE在什么情况下使用索引,举的例子是:

create table t1 (tid number(1),tidc varchar2(1));
insert /*+append* into t1 select rownum,rownum from all_objects where rownum<10;
create index i1 on t1(tid);

这时一共有九行数据,在数据文件里应该不会超过1个数据块。他本来想演示在加函数的情况下,索引会无法使用。但是这时发现即使用以下查询依然不会使用索引:
select * from t1 where tid=1;

于是奇怪之,删掉索引,重新建了一个唯一索引,这时数据库才能正常使用索引(在做范围扫描的时候肯定会失效)。

他的查询没有使用索引的原因在于他没有对表进行分析,优化器拿到了错误的信息,因此觉得全表扫描更划算(当然在这种情况下实际上全表扫描更划算一些)。

但是按我的估计,ORACLE在执行这个查询的时候,什么情况下都不该使用索引。因为在只有9行数据(占一个块)的情况下,全表扫描更划算。后来对表做了分析,发现t4表占据了5个数据块(可能是因为元数据的关系,需要查证)(pct_free10,pct_used90),这样的话就可以解释为什么数据库会选择使用索引了。因为全表扫描需要扫描五个块,而索引扫描只需要两个块。

只是我不清楚,ORACLE在计算成本的时候是不是应该将包含表的元数据的数据块抛去不算,这样的话计算才正确一些。

没有评论: