表:  table1 (  year char(4) , month char(2) , c int )
索引:index1 ( year , month )
      index2 ( c )
------------------------------------------------------
比较1:
    SQL1:select * from table1 where c >= 1 and c <= 5
    SQL2: select * from table1 where c between 1 and 5
比较2:
    SQL1:select * from table1 where c = 1 or c = 5
    SQL2: select * from table1 where c in ( 1 ,5 )
比较3:
    SQL1:select * from table1 where year+month = '200401' 
    SQL2:select * from table1 where year = '2004' and month = '01'
------------------------------------------------------
比较以上三组SQL语句的执行速度,谢谢!

解决方案 »

  1.   

    SQL1:select * from table1 where year+month = '200401'
    SQL2:select * from table1 where year = '2004' and month = '01'感觉第二中比第一种会高一些
      

  2.   

    第一和第二组的两个SQL,通常情况下性能没差别。第三组的SQL2可以用到索引,SQL1不会用到索引。此外,第三组两个SQL在oracle中含义是不同的,SQL1的year+month是把year和month都转为数值型后相加,需要改为year||month才和sql2的含义相同。
      

  3.   

    再问:
    比较4:
        SQL1:select * from table1 where c*2 = 2 or c*2 = 10
        SQL2: select * from table1 where c*2 in ( 2 , 10 )
    哪个执行速度快?
      

  4.   

    比较4 都一样,都是要进行Full Table Scan
      

  5.   

    比较一:一样的
    比较二:第二个可能比第一个好, 用or的情况下绝对是全表scan
    比较三:第二个好, 如果year, month建立了index, 第二个会用index seek而第一个是scan比较四:都一样, 但第二个条件改志c in (1, 5)后的效果比第一句强
      

  6.   

    前两组没区别....oracle会把in 自动分解成 or....or ...or的
      

  7.   

    第一的两个SQL,通常情况下性能没差别。第三组的SQL2可以用到索引,SQL1不会用到索引。此外,第三组两个SQL在oracle中含义是不同的,SQL1的year+month是把year和month都转为数值型后相加,需要改为year||month才和sql2的含义相同。
    第二组的SQL1理论比SQL2要快点
      

  8.   

    写错了
    第二组的SQL2理论比SQL1要快点
      

  9.   

    SQL2:select * from table1 where year = '2004' and month = '01'
    这个用到了索引
    其实每条语句你都可以 sql developer 中有个分析 Explain Plan可以看到是否用到索引和是否是全表扫描,如果两个表查询 一般先大表后小表
      

  10.   

    其实最好的办法是你看一下执行计划,如果oracle 8以后的版本许多分析都是基于成本的,即使是同一条语句,可能因为数据量的不同而oracle使用了不同的优化方法。
    举个例子:
    --表:ship  主键 :ship_no 
    --(1)返回的数据量比较大,oracle使用全表扫描,即使使用了索引
    select * from ship where ship_no > 1
    Plan
    SELECT STATEMENT  CHOOSECost: 6  Bytes: 308,844  Cardinality: 1,119  
    1 TABLE ACCESS FULL ZJG_GANGBU.SHIP Cost: 6  Bytes: 308,844  Cardinality: 1,119  
    --(2)返回的数据量比较小,使用索引
    select * from ship where ship_no >4000
    Plan
    SELECT STATEMENT  CHOOSECost: 3  Bytes: 828  Cardinality: 3  
    2 TABLE ACCESS BY INDEX ROWID ZJG_GANGBU.SHIP Cost: 3  Bytes: 828  Cardinality: 3  
    1 INDEX RANGE SCAN UNIQUE ZJG_GANGBU.PK_SHIP Cost: 2  Cardinality: 3  
    --(3)使用or条件 ,oracle依然使用索引
    select * from ship where ship_no = 352 or ship_no = 365Plan
    SELECT STATEMENT  CHOOSECost: 3  Bytes: 552  Cardinality: 2  
    3 INLIST ITERATOR  
    2 TABLE ACCESS BY INDEX ROWID ZJG_GANGBU.SHIP Cost: 3  Bytes: 552  Cardinality: 2  
    1 INDEX RANGE SCAN UNIQUE ZJG_GANGBU.PK_SHIP Cost: 2  Cardinality: 2  
      

  11.   

    其实比较要关注三点 :
    1、你的数据量
    2、每个列值的基数
    3、你建的索引 以上三组SQL 不用看执行计划就可以判断第一组和第二组中 两条SQL的执行路径是一样的 为什么呢 因为他们都会选择index range scan 就是索引范围扫描,如果c列数据更新很少或者根本不更新的话 创建bitmap索引,速度会更快
    第三组SQL就不一样了 因为你创建的是个组合索引 那么索引的存储也是对每个列分别存储的
    所以 
    SQL1:select * from table1 where year+month = '200401' 
    这个SQL执行的是全表扫描 根本不会走索引扫描 因为它在索引中只会发现year=2004 和month=01 发现不了'200401'这个索引  SQL2:select * from table1 where year = '2004' and month = '01' 肯定会走索引扫描
    速度明显高于SQL1呵呵 楼住如果是做开发的话 不妨看看ORACLE的 Performance Tuning文档 上面讲的很详细的