发信人: pengxiaohui(韦小宝) 
整理人: xiaomiao(2002-04-03 09:00:36), 站内信件
 | 
 
 
二、索引也有好坏 
     索引有 B tree 索引, Bitmap 索引, Reverse b tree 索引, 等。最常用的是 B tree 索引。 B 的全称是Balanced , 其意义是,从 tree 的 root 到任何一个leaf ,要经过同样多的 level. 索引可以只有一个字段(Single column), 也可以有多个字段(Composite),最多32个字段,8I 还支持 Function-based index. 许多developer 都倾向于使用单列B 树索引。 
 
 所谓索引的好坏是指: 
 
     1,索引不是越多越好。特别是大量从来或者几乎不用的索引,对系统只有损害。OLTP系统每表超过5个索引即会降低性能,而且在一个sql 中, Oracle 从不能使用超过 5个索引。 
 
 2,很多时候,单列索引不如复合索引有效率。 
 
 3,用于多表连结的字段,加上索引会很有作用。 
 
     那么,在什么情况下单列索引不如复合索引有效率呢?有一种情况是显而易见的,那就是,当sql 语句所查询的列,全部都出现在复合索引中时,此时由于 Oracle 只需要查询索引块即可获得所有数据,当然比使用多个单列索引要快得多。(此时,这种优化方式被称为 Index only access path) 
 
 除此之外呢?我们还是来看一个例子吧: 
 
 在 HP(Oracle 8.1.7) 上执行以下语句: 
 
 select count(1) from mytabs where coid>=130000 and issuedate >= to_date ('2001-07-20','yyyy-mm-dd')。 
 
     一开始,我们有两个单列索引:I_mytabs1(coid), I_mytabs2(issuedate), 下面是执行情况: 
 
 COUNT(1) 
 
 ---------- 
 
 6427 
 
 Execution Plan 
 
 ---------------------------------------------------------- 
 
 0 SELECT STATEMENT Optimizer=CHOOSE (Cost=384 Card=1 Bytes=11) 
 
 1 0 SORT (AGGREGATE) 
 
 2 1 TABLE ACCESS (BY INDEX ROWID) OF 'T_MYTABS' (Cost=384 Card 
 
 =126 Bytes=1386) 
 
 3 2 INDEX (RANGE SCAN) OF 'I_MYTABS2' (NON-UNIQUE) (Cost=11 
 
 Card=126) 
 
 Statistics 
 
 ---------------------------------------------------------- 
 
 172 recursive calls 
 
 1 db block gets 
 
 5054 consistent gets 
 
 2206 physical reads 
 
 0 redo size 
 
 293 bytes sent via SQL*Net to client 
 
 359 bytes received via SQL*Net from client 
 
 2 SQL*Net roundtrips to/from client 
 
 5 sorts (memory) 
 
 0 sorts (disk) 
 
 1 rows processed 
 
 可以看到,它读取了7000个数据块来获得所查询的 6000多行。 
 
 现在,去掉这两个单列索引,增加一个复合索引I_mytabs_test ( coid, issuedate), 重新执行,结果如下: 
 
 COUNT(1) 
 
 ---------- 
 
 6436 
 
 Execution Plan 
 
 ---------------------------------------------------------- 
 
 0 SELECT STATEMENT Optimizer=CHOOSE (Cost=3 Card=1 Bytes=11) 
 
 1 0 SORT (AGGREGATE) 
 
 2 1 INDEX (RANGE SCAN) OF 'I_MYTABS_TEST' (NON-UNIQUE) (Cost=3 Card=126 Bytes=1386) 
 
 Statistics 
 
 ---------------------------------------------------------- 
 
 806 recursive calls 
 
 5 db block gets 
 
 283 consistent gets 
 
 76 physical reads 
 
 0 redo size 
 
 293 bytes sent via SQL*Net to client 
 
 359 bytes received via SQL*Net from client 
 
 2 SQL*Net roundtrips to/from client 
 
 3 sorts (memory) 
 
 0 sorts (disk) 
 
 1 rows processed 
 
 可以看到,这次只读取了300个数据块。 
 
 7000块对300块,这就是在这个例子中,单列索引与复合索引的代价之比。这个例子提示我们, 在许多情况下,单列索引不如复合索引有效率。 
 
 可以说,在索引的设置问题上,其实有许多工作可以做。正确地设置索引,需要对应用进行总体的分析。 
  | 
 
 
 |