有个performance的问题想请问大家,请先看下面这个示意的select语句
select count(*) 
from A, B, C
where A.field1 = C.field1
  and A.field2 = B.field2
  and A.date >= to_date('2005-01-01', 'yyyy-mm-dd')
  and A.date < to_date('2006-01-01', 'yyyy-mm-dd');表A是个大表,大概有300万条记录。表B和C都是小表。表A在字段date上建有索引。
整个语句执行的时候大概是200秒,如果去除最后两个and条件,可以达到20多秒这样的十位数量级的速度,如果把最后两个and条件变成'A.date = to_date('2005-01-01', 'yyyy-mm-dd')’,速度会更快。
但是需求就是要求在一个时间范围类搜索记录。
我的问题有两个:
[1] 'and A.date >= to_date('2005-01-01', 'yyyy-mm-dd') and A.date < to_date('2006-01-01', 'yyyy-mm-dd')' 这两个条件中是否会使用索引?因为我听说如果在索引字段上使用函数,就不会走索引。
[2] 如何提高示意语句的performance,能够提高到100秒也是好的。
先谢谢大家的踊跃发言:)。

解决方案 »

  1.   

    [1]会用
    to_char(A.date,'yyyy-mm-dd')   对字段用函数就用不到了[2]不知道
    如果时间段很短,出来的数据远小于300万,可以先select a
    select * from A where date >= to_date('2005-01-01', 'yyyy-mm-dd')
      and date  < to_date('2006-01-01', 'yyyy-mm-dd'); 
    再做运算
      

  2.   

    谢谢对第一个问题的答复。
    对于第二个问题,
    select * from A 
    where date >= to_date('2005-01-01', 'yyyy-mm-dd') 
      and date   < to_date('2006-01-01', 'yyyy-mm-dd'); 
    选出来的数据量也不小,如果是一年的范围,一般是60多万条记录。我希望的是能够在一条select语句完成所有的运算。如果是先选出来再做运算,就得写成procedure,因为这个select语句其实是上层的C++界面程序调用完成的。
      

  3.   

    select /*+ full(A)*/count(*)  
    from A, B, C 
    where A.field1 = C.field1 
      and A.field2 = B.field2 
      and A.date >= to_date('2005-01-01', 'yyyy-mm-dd') 
      and A.date  < to_date('2006-01-01', 'yyyy-mm-dd'); 
    让索引失效看看,应该跟
    select count(*)  
    from A, B, C 
    where A.field1 = C.field1 
      and A.field2 = B.field2;
    性能差不多,你访问了表里面的1/5的数据,再用索引就不能其到加快速度的效果,反而起反作用了
      

  4.   

    同意3楼,
    A.date+0 >= to_date('2005-01-01', 'yyyy-mm-dd')  
      and A.date+0   < to_date('2006-01-01', 'yyyy-mm-dd'); 也可以使用索引失效。 
      

  5.   

    创建一个复合索引:create index idx_a_xxx on a(field1, field2, date);再anaylze这个索引。让oracle走这个索引, 而不是走表A的 full scan
      

  6.   

    "表B和C都是小表"这两个表有多小,如果只有行或几十行的话不如把它写在where里面,这样应该会快很多,如c,b各有5条数据的话,from a,b,c 就相当于查一个300万×5×5=7500万的一个表了,把b,c写在条件里的话只是一个300万的表,另外不要用to_date函数,用(sysdate-天数)试试看
      

  7.   

    或者用子查询试试
    select count(*)  
    from 
    (select * from 
    (select * from a,b where and A.field2 = B.field2 ) t1,
    (select * from a,c where and A.field1 = C.field1 ) t2) t
    where t.data between sysdate-天数1 and sysdate-天数2