首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > oracle >

SQL语句执行速度有关问题

2012-01-14 
SQL语句执行速度问题。表:table1(yearchar(4),monthchar(2),cint)索引:index1(year,month)index2(c)-------

SQL语句执行速度问题。
表:     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语句的执行速度,谢谢!


[解决办法]
SQL1:select * from table1 where year+month = '200401 '
SQL2:select * from table1 where year = '2004 ' and month = '01 '

感觉第二中比第一种会高一些
[解决办法]
第一和第二组的两个SQL,通常情况下性能没差别。第三组的SQL2可以用到索引,SQL1不会用到索引。此外,第三组两个SQL在oracle中含义是不同的,SQL1的year+month是把year和month都转为数值型后相加,需要改为year||month才和sql2的含义相同。
[解决办法]
比较4 都一样,都是要进行Full Table Scan
[解决办法]
比较一:一样的
比较二:第二个可能比第一个好, 用or的情况下绝对是全表scan
比较三:第二个好, 如果year, month建立了index, 第二个会用index seek而第一个是scan

比较四:都一样, 但第二个条件改志c in (1, 5)后的效果比第一句强
[解决办法]
第一的两个SQL,通常情况下性能没差别。第三组的SQL2可以用到索引,SQL1不会用到索引。此外,第三组两个SQL在oracle中含义是不同的,SQL1的year+month是把year和month都转为数值型后相加,需要改为year||month才和sql2的含义相同。
第二组的SQL1理论比SQL2要快点
[解决办法]
SQL2:select * from table1 where year = '2004 ' and month = '01 '
这个用到了索引
其实每条语句你都可以 sql developer 中有个分析 Explain Plan可以看到是否用到索引和是否是全表扫描,如果两个表查询 一般先大表后小表
[解决办法]
其实最好的办法是你看一下执行计划,如果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 = 365

Plan
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


[解决办法]
其实比较要关注三点 :
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文档 上面讲的很详细的

热点排行