查询语句:
        select * from web_gjcgs_info t where sysdate < t.end_time order by t.fb_time desc
表结构:
      
目前:
    select count(1) from web_gjcgs_info t
    一共有13600行    select count(1) from web_gjcgs_info t where sysdate < t.end_time
    有12963行现在在表上的 end_time, fb_tim e列上各自都建立一个B*索引    fb_time 为not null (oracle 排序走索引一定要为非空)执行:  select * from web_gjcgs_info t where sysdate < t.end_time order by t.fb_time desc
查看执行计划:
        
         查询时间为0.13秒左右
他选择了走 end_time 的索引区间读区间读 由于我的是查询select * 还要根据RowID去查询表
      问题1: oracle分析执行计划的时候他会计算聚簇因子 上面已经贴出
              select count(1) from web_gjcgs_info t
              一共有13600行
              select count(1) from web_gjcgs_info t where sysdate < t.end_time
              有12963行
              他的查询数量非常大由于索引时随即排序的最后还是要根据RowID去表里面找
              他的聚簇因子很大他应该选择区全表扫
现在我把end_time, fb_tim e列上的索引区去表让他去全表扫描
        执行发现时间也为0.13秒左右
我的猜测他走索引所消耗的IO数量肯定比走全表扫描多的多(虽然时间差不多)
为什么他会选择去做索引而没去走全表扫描呢问题2:
      select * from web_gjcgs_info t where sysdate < t.end_time order by t.fb_time desc 既然上面where sysdate < t.end_time 走了end_time 的索引去表读 那我能where sysdate < t.end_time走索引区间读  order by t.fb_time desc 走缩影排序么
我在 建立了一个复合索引   顺序为end_time ,fb_time 发现他走了这个复合索引 走的却是end_time的区间索引 没走fb_time 的排序
我删除了顺序为end_time ,fb_time 的复合索引
建一个fb_time ,end_time 的复合索引 他却什么都没走 走的是全表扫描
我那所有索引都删了 只建一个fb_time  的一个索引他走了这个索引时间直接降到0.03秒
1:我认为不因该去选择走 end_time的索引范围差应为他的聚簇因子很大
2:既然他走了end_time的索引为什么他就是不足fb_time的缩影的
       

解决方案 »

  1.   

    对于问题1:先确定一下你的统计信息是不是正确,如果统计信息正确的话,再确定一下你的oracle版本,如果是9i的话,会把sysdate作为绑定变量来看待,这样oracle就会认为你想要的数据占整个表的5%,oracle也就走索引了,而且,查询走索引还是走全表扫描,主要是看你查询的数据量占整个表的百分比,聚簇因子是次要的因素对于问题2:对于复合索引,首先会根据查询条件对比复合索引中的第一个字段,如果对比不上,则放弃索引
      

  2.   

    一个表一次查询只能走一个索引,只建立fb_time索引时,oracle根据该索引取数据,使排序时间大大降低。
    而排序的时间远大于数据过滤的时间。