ORACLE索引使用总结

 

一:索引基本概念

oracle提供了两种方式,从表中读取所有行(即全表扫描),或者通过ROWID一次读取一行;

如果只访问大数据量表的5%的行,并且使用索引标识需要读取的数据块,这样花费的 I/O 较少,索引对性能的改进程度: 1.取决于数据的选择性 2.数据在表的数据块中的分步方式;

当数据分散在表的多个数据块时,最好是不使用索引,而是使用全表扫描,执行全表扫描时,oracle使用多块读取以快速扫描表,基于索引的读是单块读,因此在使用索引时的目标是减少完成查询所需的单块读的数量;

增强索引会降低 insert 语句的性能(因为需要同时对表和索引进行更新),大量行的 delete 操作,将会由于表中存在索引而变慢;

在SQL中有许多陷阱会使一些索引无法使用:

1.使用不等于运算符

索引只能查找表中已存在的数据,每当在 where 子句中使用不等于运算符时,其中被用到的列上的索引都将无法使用;例如:select cust_id, cust_name from customers where cust_rating <> 'aa'; oracle在分析表的同时收集数据分布的相关统计信息,通过这种方法,基于成本的优化器可以决定在where子句中对一些值使用索引,而对其他值不使用索引;

可以使用 create index 命令的 compute statistic 子句,在创建索引的同时分析它们;

2.使用 ISNULL

当在where子句中使用ISNULL的时候,因为NULL值并没有被定义(oracle不会再B树索引中对NULL值索引),所以索引的使用会被抑制,数据库中没有值等于NULL,甚至NULL也不等于NULL;如果被索引的列在某些行中存在NULL值,在索引中就不会有相应的条目(除非使用位图索引,这是位图索引对于NULL搜索很快的原因);例如:select empno, deptno from emp where sal is null; 即使sal列上有索引,也会进行全表扫描;

3.使用LIKE

条件中有LIKE关键字会使用索引,通常有两种写法 LIKE '%some%' 或 LIKE ‘%some’ 或 LIKE ‘some%’ ;当%在前面的时候,索引不会被使用,但是当值在前面的时候,oracle可以使用索引;

4.使用函数

除非使用基于函数的索引,否则在SQL语句的where子句中对存在的索引的列使用函数时,优化器会忽略索引,一般常见的函数如:TRUNC, SUBSTR, TO_DATE, TO_CHAR 和 INSTR 等,

例如下面的SQL就会使用全表扫描,

select empno, deptno from emp where trunc(hiredate) = '01-MAY-01' ;

改成下面就可以了

select empno, deptno from emp where hiredate > '01-MAY-01' and hiredate < (TO_DATE('01-MAY-01' ) + 0.99999);

通过改变所比较列上的值,而不用改变列本身,就可以启用索引,这样可以避免全表扫描;

5.比较不匹配的数据类型(隐式转换)

一种很难解决的性能问题是比较不匹配的数据类型,oracle不但不会对那些不兼容的数据类型报错,反而会做隐式数据转换。例如:oracle可以隐式转化 varchar2 类型的列中的数据去匹配数值类型数据;

如果account_number列是varchar2数据类型,下面将进行全表扫描: select bank_name, address, city, state, zip from banks where account_number = 99999; oracle会自动转换成 to_number(account_number) = 99999 ; 这样就抑制了索引的使用;

如果上面的语句加上单引号就会使用索引。select bank_name, address, city, state, zip from banks where account_number = '99999';

  1. OR关键字的使用,会抑制索引,下面使用OR,即使是索引列,数据类型匹配,仍会抑制索引的使用

select bank_name, address, city, state, zip from banks where account_number = '99999' or account_number = '88888' ;

改成 AND 或 IN ,oracle就可以使用索引的

 

集群因子

集群因子(CLUSTERING_FACTOR)是对表的有序性的量度,通过一个索引扫描一张表时需要访问表的数据库的数量;

一个字段上有索引,但有时执行sql语句时看执行计划时不走索引,就有可能是集群因子过高导致的。

计算方法:1.扫描一个索引 2.标胶某行的 rowid 和前一行的 rowid,如果这两个 rowid 不属于同一个数据块,那么集群因子+1 3.整个索引扫描完毕得到集群因子的值

 

 

如果集群因子接近于表中块的数量,则表示索引适当排序;如果集群因子接近于表中行的数量,则表示索引没有适当排序

优化执行计划总结

1.避免索引列的隐式转换;

2.匹配索引的前导列(组合/复合索引):如果索引是建立在多个列上,只有在它的前导列被where子句引用时,优化器才会选择使用该索引;

3.使用ROWID;

4.避免对索引列 使用 OR、函数运算(TRUNC、TO_DATE、TO_CHAR等)、计算等操作;可以使用AND、IN、UNION代替对索引列使用OR操作;

5.减少函数的调用;

6.减少语句中表的访问次数;

7.避免笛卡尔集;