Oracle索引详解(二)
--索引分类
??Oracle 提供了大量索引选项。知道在给定条件下使用哪个选项对于一个程序的性能来说非常重要。一个错误的选择可能会引发死锁,并导致数据库性能急剧下降或进程终止。而如果做出正确的选择,则可以合理使用资源,使那些已经运行了几个小时甚至几天的进程在几分钟得以完成,极大的提高数据操作语句的运行效率。
导读【2017-12-26】【22:35:36】:
-
- B 树索引(默认类型)
- 位图索引
-
HASH 索引
- 索引组织表索引
- 反转键(reverse key)索引
- 基于函数的索引
- 分区索引(本地和全局索引)
- 位图连接索引
- B 树索引(默认类型)
一、B 树索引
B 树索引在 Oracle 中是一个通用索引。在创建索引时它就是默认的索引类型。B 树索 引可以是一个列的(简单)索引,也可以是组合/复合(多个列)的索引。B 树索引最多可以包括 32 列。 索引列的值都存储在索引中。因此,可以建立一个组合(复合)索引,这些索引可以直 接满足查询,而不用访问表。这就不用从表中检索数据,从而减少了 I/O 量。
特点:
- 适合与大量的增、删、改(OLTP);
- 不能用包含 OR 操作符的查询;
- 适合高基数的列(唯一值多);
- 典型的树状结构;
- 每个结点都是数据块; 大多都是物理上一层、两层或三层不定,逻辑上三层;
- 叶子块数据是排序的,从左向右递增;
- 在分支块和根块中放的是索引的范围;
二、位图索引
位图索引非常适合于决策支持系统(Decision Support System,DSS)和数据仓库,它们不应该用于通过事务处理应用程序访问的表。它们可以使用较少到中等 基数(不同值的数量)的列访问非常大的表。尽管位图索引最多可达 30 个列,但通常它们都只用于少量的列。对于有较低基数的列需要使用位图索引,比如性别。 在一个查询中合并多个位图索引后,可以使性能显著提高。位图索引 使用固定长度的数据类型要比可变长度的数据类型好。较大尺寸的块也会提高对 位图索引的存储和读取性能。
特点:
- 适合与决策支持系统;
- 做 UPDATE 代价非常高;
- 非常适合 OR 操作符的查询;
- 基数比较少的时候才能建位图索引;
三、HASH 索引
使用 HASH 索引必须要使用 HASH 集群。建立一个集群或 HASH 集群的同 时,也就定义了一个集群键。这个键告诉 Oracle 如何在集群上存储表。在存储数据时,所有与这个集群键相关的行都被存储在一个数据库块上。 HASH 索引在有限制条件(需要指定一个确定的值而不是一个值范围)的情况下非常有用。
特点:
- HASH 索引可能是访问数据库中数据的最快方法,但它也有自身的缺点,低估了集群键的不同值的数字可能会造成集群的冲突 ;
- 如果不能为集群的未来增长分配好附加的空间,HASH 集群可能就不 是最好的选择;
- 如果应用程序经常在集群表上进行全表扫描,HASH 集群可能也 不是最好的选择;
- 通常,HASH 对于一些包含 有序值的静态数据非常有效;
四、索引组织表
索引组织表会把表的存储结构改成 B 树结构,以表的主键进行排序。这种特殊的表和其他类型的表一样,可以在表上执行所有的 DML 和 DDL 语句。由于表的特殊结构,ROWID 并没有被关联到表的行上。
对于一些涉及精确匹配和范围搜索的语句,索引组织表提供了一种基于键的快速数据访问机制。基于主键值的 UPDATE 和 DELETE 语句的性能也同样得以提高,这是因为行在物理上有序。由于键列的值在表和索引中都没有重复,存储所需要的空间也随之减少。
如果不会频繁地根据主键列查询数据,则需要在索引组织表中的其他列上创建二级索引。不会频繁根据主键查询表的应用程序不会了解到使用索引组织表的全部优点。对于总是通过对主键的精确匹配或范围扫描进行访问的表,就需要考虑使用索引组织表,可以在索引组织表上建立二级索引
五、反转键索引
当载入一些有序数据时,索引肯定会碰到与 I/O 相关的一些瓶颈。在数据载 入期间,某部分索引和磁盘肯定会比其他部分使用频繁得多。为了解决这个问题, 可以把索引表空间存放在能够把文件物理分割在多个磁盘上的磁盘体系结构上。
为了解决这个问题,Oracle 还提供了一种反转键索引的方法。如果数据以反转键索引存储,这些数据的值就会与原先存储的数值相反。这样,数据 1234、1235 和 1236 就被存储成 4321、5321 和 6321。结果就是索引会为每次新插入 的行更新不同的索引块。
技巧:
- 如果您的磁盘容量有限,同时还要执行大量的有序载入,就可以使用反转键索引。
- 不可以将反转键索引与位图索引或索引组织表结合使用。因为不能对位图索引和索引组织表进行反转键处理。
六、基于函数的索引
可以在表中创建基于函数的索引。如果没有基于函数的索引,任何在列上执行了函数的查询都不能使用这个列的索引。例如,下面的查询就不能使用 JOB 列上的索引,除非它是基于函数的索引:
1 select * from emp where UPPER(job) = ‘MGR‘;
下面的查询使用 JOB 列上的索引,但是它将不会返回 JOB 列具有 Mgr 或 mgr 值的行:
1 select * from emp where job = ‘MGR‘;
可以创建这样的索引,允许索引访问支持基于函数的列或数据。可以对列表 达式 UPPER(job)创建索引,而不是直接在 JOB 列上建立索引,如:
1 create index EMP$UPPER_JOB on emp(UPPER(job));
尽管基于函数的索引非常有用,但在建立它们之前必须先考虑下面一些问题:
- 能限制在这个列上使用的函数吗?如果能,能限制所有在这个列上执行的所有函数吗?
- 是否有足够应付额外索引的存储空间?
- 在每列上增加的索引数量会对针对该表执行的 DML 语句的性能带来何种影响?
基于函数的索引非常有用,但在实现时必须小心。在表上创建的索引越多,INSERT、UPDATE 和 DELETE 语句的执行就会花费越多的时间。 注意:对于优化器所使用的基于函数的索引来说,必须把初始参数 QUERY_REWRITE _ ENABLED 设定为 TRUE。
示例:
1 select count(*) from sample where ratio(balance,limit) >.5; 2 time: 20.1 minutes 3 4 create index ratio_idx1 on sample (ratio(balance, limit)); 5 6 select count(*) from sample where ratio(balance,limit) >.5; 7 time: 7 seconds