1)b-tree索引
Oracle数据库中最常见的索引类型是b-tree索引,也就是B-树索引,以其同名的计算科学结构命名。每当你发布基本的没有经过进 一步修改的CREATE INDEX语句时,就是在创建b-tree索引。这里不打算对b-tree索引进行更多深入的探讨,这些用户都可以自己了解。基本上这些索引存储你创建的 索引所在的列值以及用来查找自身行的指向实际数据表的指针。记住,这也就意味着要进行多路查询,其中一个查询各个节点和索引的叶节点,然后才是表的行自 身。这就是为什么Oracle的优化器在某种情况下会选择执行全表扫描而不执行索引查找的原因了,因为全表扫描执行起来实际上可能会更快一些。还要注意的 是,如果你的索引是创建在多个列上的话,那么第一列(leading column)非常重要。假设你有一个多列索引(也称为级联索引),索引列的排列顺序是c列到d列,你可以对使用该索引c列单独进行一次查询,但你不能使 用该索引对d列冶金行一次单独的查询。
2)基于函数的索引
如果在搜索时你读取很多行,或者你的索引选择性不大,又或者你在级联索引中使用了第一列以外的列,Oracle数据库有时候会选择不使用索 引。那么如果你想要执行一个大小写不敏感的搜索呢?像下面的指令:WHERE UPPER(first_name) = ‘JOHN’。
这也不会使用first_name字段上的索引。为什么?因为Oracle不得不将UPPER函数用在该索引所有(ALL)的值上,所以还不如做一次全表扫描。所以,很多时候Oracle创建基于函数的索引就是为了这个目的。
3)反转关键字索引
你还可以看到这些反转关键字索引,而且不时还要用到这些索引。假设有一列包含了“餐厅甲”、“餐厅乙”、“餐厅丙”等类似名字。可能这不是 一个很好的例子,不过关键的一点是拥有很多唯一值,但其关键字的前面一部分变化不大。因为Oracle会在将REVERSE关键字指定给b-tree前把 REVERSE字符串简化,所以使用反转关键字索引可能是最好的。这样的一个索引可能更平衡、有用,搜索起来更快。
更多外部索引类型
Oracle还提供了很多更为复杂的索引类型。不过请注意,你最好全面阅读过相关的说明文档后再使用这些索引,因为它们各自都有各自特定的适用范围。
1)位图索引(bitmap index)
假设数据库表中有一列其选择性非常窄,例如性别列,该用什么类型的索引?你可能会考虑对其使用位图索引。因为位图索引正是为相异值很少的列 而创建的。但需要考虑的因素还不只这些。一般而言,只有当你对表中值相宜度较小的多个不同的列都使用位图索引,这样位图索引才有用,因为你可以一起使用这 些索引才能对列产生更大的选择性,否则你还是需要对这些列进行一次全表扫描。例如,对于性别列,其索引只能有两个唯一值,那么用这个索引对表的任何搜索有 可能都返回一半的记录。其次,这些索引是为数据仓库而设计的,所以其假定条件是数据不会发生很大的改变。这些索引不能用来满足事务数据库或更新频繁的数据 库。应该说,对位图索引的表进行更新根本没有一点效率。
2)位图连接索引(bitmap join index)
位图连接索引比位图索引更进了一步。这些索引将位图化的列完全从表数据中抽取出来,并将其存储在索引中。其假定条件是这些列集合必须一起查 询。同样的,这也是为数据仓库数据库而设计的。除了在句法最后有一个WHERE子句之外,位图连接索引的创建指令就像创建位图索引的CREATE BITMAP INDEX一样。
3)压缩索引
压缩索引实际是标准b-tree索引的一个选项。压缩索引的叶节点更少,所以总的I/O数量和需要的缓存也更少。这些都意味着Oracle 的优化器更可能使用这些压缩索引,而不倾向于使用标准的非压缩索引。不过,这些好处也是有代价的,当你对这些压缩索引进行存取操作时,要消耗更多的CPU 来进行解压缩。而且,当你阅读关于优化器如何使用这些索引,又是如何选择合适的压缩级别的资料时,就开始变得晦涩了。不同的用户不同的设置从压缩索引中得 到的好处也可能会有所不同。
4)降序索引(descending index)
这是基于函数索引的一种特殊类型。降序索引可以显著优化ORDER BY x, y, z DESC子句查询的。
5)分区索引(partitioned index)
如果你的数据库中有一个分区表,你就有机会体验几种新的索引类型,从贯穿所有分区的全局分区索引(global)和集中于各个单独分区的本地分区索引(local)。这里不再进行赘述,想知道细节问题可以查询相关文献。
6)索引组织表(index organized table,IOT)
这是在Oracle 9i中引进的一种新类型表。Oracle会将级联索引及其扩展类型的索引用于表中所有的列。当所有数据都载入到索引结构之后,表就成多余的了,你尽可以将表本身删除掉。这就是索引组织表。
7)簇索引(cluster index)
基本上,簇索引就是将多个表的相同列放在一起,而对该列使用用一个簇索引。这种索引在实际应用中比较少,因为还有各种有待解决的性能问题存在。
8)域索引(domain index)
当我们创建为用户自定义数据类型(datatype)创建用户自定义索引类型(indextype)时就要使用域索引。
9)隐藏索引(invisible index)
这是Oracle 11g中推出的新特性。其创建过程和标准索引一样,但创建后对于基于代价的优化器(CBO)是不可见的。这可以让你对性能进行大型测试查询,而不会影响现有的正在运行的应用程序。
10)虚拟索引(virtual index)
这是为测试人员和开发人员准备的又一个工具。虚拟索引(不分配段空间)可以让你在不需要实际创建索引的情况下,测试新索引及其对查询计划的影响。对于GB级的表来说,构建索引非常耗费资源而且还要占用大量时间。
11)其他的索引类型
Oracle数据库还提供了很多其他类型的索引,例如用来为字符型大型二进制对象(CLOB)或其他大型文本数据构建索引的Oracle TEXT,Oracle Spatial等。有兴趣的读者可以自己查找相关资料了解。
都是为了优化器
如果你曾经广泛接触过MySQL和其他的数据库,你会发现甲骨文虽然是全球领先的数据库供应商,但它们的数据库对于用户来说用起来其实并不 是很方便。提到优化器这个问题可能有点离题了,不过Oracle数据库最基本的食料就是优化器了,这的确是种挺特别的调料,而且变得越来越美味了。市面上 有很多以Oracle基于代价的优化器(Cost Based Optimizer,CBO)为主题内容的书籍,专门介绍分析表和索引的技巧和策略。
对于数据库,除了需要一直更新你的统计信息之外,你可能还需要不断测试新的查询。使用解析计划机制,并进行优化以便减少总I/O量以及排序和合并数据的计算量,只有这样你才能获得更好的性能表现。
总结
虽然Oracle数据库的索引世界有点吓人,不过实际上你平常经常使用的索引就只有那么一些。而且,不管唱反调的人怎样诋毁,Oracle 的优化器都已经设计相当出色;总体而言,Oracle很擅长于让你的数据库运行地更有效率。虽然这并不意味着你不需要对自己的SQL进行调优,不过,如果 你一直保持着最新的统计信息,并让Oracle为你整理出你所需要的最小数据集的话,它能够以极快的速度满足你的需要。