我有一张表有三个字段,
startip(number)      endip (number)       area(varchar2)
数据量共有7万条左右,我在STARTIP, ENDIP上建有索引
create index WORLDIP_IP_INDEX on WORLDIP (STARTIP, ENDIP)
  tablespace USERS
  pctfree 10
  initrans 2
  maxtrans 255
  storage
  (
    initial 64K
    minextents 1
    maxextents unlimited
  );
我去执行查询的时候,为什么有的时候用了索引,有的时候没有用索引呢?
查询语句如下:
select AREA from worldip T where 2068239936 between T.startip and T.endip
小弟oracle菜鸟,请各路神仙高手帮帮我……

解决方案 »

  1.   


    执行计划
    ----------------------------------------------------------
       0      SELECT STATEMENT Optimizer=ALL_ROWS (Cost=56 Card=15210 Byte
              s=258570)   1    0   TABLE ACCESS (FULL) OF 'WORLDIP' (TABLE) (Cost=56 Card=152
              10 Bytes=258570)统计信息
    ----------------------------------------------------------
              0  recursive calls
              0  db block gets
            249  consistent gets
              0  physical reads
              0  redo size
            467  bytes sent via SQL*Net to client
            435  bytes received via SQL*Net from client
              2  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
              1  rows processed
    以上是小弟的执行计划,也不晓得全不全
      

  2.   

    select AREA from worldip T where T.startip >2068239936  and T.endip <2068239936 
      

  3.   

    试过了 还是一样 没有变化 
    select * from worldip t where 2068239936 >= startip and 2068239936 <=endip
    执行计划
    ----------------------------------------------------------
       0      SELECT STATEMENT Optimizer=ALL_ROWS (Cost=56 Card=15210 Byte
              s=258570)   1    0   TABLE ACCESS (FULL) OF 'WORLDIP' (TABLE) (Cost=56 Card=152
              10 Bytes=258570)统计信息
    ----------------------------------------------------------
              1  recursive calls
              0  db block gets
            249  consistent gets
              0  physical reads
              0  redo size
            467  bytes sent via SQL*Net to client
            435  bytes received via SQL*Net from client
              2  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
              1  rows processed
      

  4.   

    你先收集统计信息,再执行sql,否则加hint
      

  5.   

    Card=15210
    ======================
    总的数据量多少?返回数据的百分比多大?如果 selectivity 太低,索引不会起作用。
      

  6.   

    大侠,总的数据量有7万条左右,每次给定一个整数,然后返回area字段,基本上就是返回一条数据,语句用的是:select * from worldip t where 2068239936 >= startip and 2068239936 <=endip 
      

  7.   

    1. 你的area字段长度是多少?如果长度少,索引可以改成:
       create unique index WORLDIP_IP_INDEX on WORLDIP (STARTIP, ENDIP, area) ;
    /
       begin
    --收集统计信息
           dbms_stats.gather_table_stats(user, 'WORLDIP', CASCADE=>TRUE);
       end;
    /
    2. sql语句写成:select * from worldip t where startip <= 2068239936  and endip >= 2068239936;这个写法比较好看3. 若你的startip, endip2个字段的数值分布不均匀,10g的CBO无法收2个字段上的直方图,可用hint强制使用索引select /*+ index(t WORLDIP_IP_INDEX) */ * from worldip t where startip <= 2068239936  and endip >= 2068239936;
      

  8.   


    按照你得做了,表是按照你写的那个语句分析的,可是还是那样的结果,执行计划没有变,基本上一样。
    我这个表里面的数据室一次性加入的,大约7万条,以后就固定了,基本上没有插入和删除,每次都是查询出一条数据,
    为何排在表前面的字段,查询的时候会用到索引,而靠后的数据就不行了呢?我在网上查到,貌似是oracle 10g采用的默认方式的基于代价的方式,当oracle发现用索引的代价比用全表扫描的代价高时,就会自动采用全表扫描的方式……但是我就是想提高查询的效率,想让查询每条数据的开销基本上都差不多,这个要怎么解决? 我想oracle肯定有相应的办法,只是我太菜不晓得,所以只能求救各位大哥了
      

  9.   

    你的索引并非唯一索引,请检查你的索引字段在表中是否能为空,如果可以为空,那么oracle有时候就会放弃使用索引。
      

  10.   

    FIRST_ROWS 已经试过 没有变……开销反而加大了 
      

  11.   

    3. 若你的startip, endip2个字段的数值分布不均匀,10g的CBO无法收2个字段上的直方图,可用hint强制使用索引 select /*+ index(t WORLDIP_IP_INDEX) */ * from worldip t where startip <= 2068239936  and endip >= 2068239936; 
    用这个呢? 效果如何?
      

  12.   


    你之前建的索引属于多码索引,如果startip和endip是主码的话可能影响不大,否则进行范围查询时使用辅助索引速度会非常的慢。如果你那张表更新的频率不频繁的话,建议使用位图索引。
      

  13.   

    先使用下面语句生成统计信息,再查看查询计划看是否有改变:analyze table t compute statistics