《Oracle数据库性能优化》笔记 – 索引与 bitmap 索引

需要复杂技巧及高深知识来解决所遇到的问题的情形并不多,相对来说,在对基本概念有清晰认识的情形下,解决问题的切入口通常都会比较准确。

索引的作用

索引是以最快的路径找到所需要的数据;另一个功用是对数据完整性的强制控制。

在下面两种情形下,系统会自动为表的列建立索引:

  1. 当表的列被指定为 primary key 时;
  2. 当表的列有 unique constraint 时。

当一个表中有 foreign key 存在时,通常也建议这个列使用索引。

索引管理的常见问题

  1. 最近是否做过数据库的分析
  2. 索引的数量,过多或过少都是不好的

索引不被使用的情况

  • 当对同一个表的两个列进行比较的情形下,索引有时不会被使用。

  • null 值。如果 where 语句中出现 is null 或者 is not null 时,索引就不能被使用。

  • 当 where 语句中存在有 not function 时,比如 not in, not exist, column <> value, column > value, column2 < value 等情形下,索引不能被使用。

  • 当 select 语句使用了 single-row function时,如 nvl, to_char, lower 等,索引不能被使用。

  • 通配符 % 或者 _ 作为查询字符串的第一个字符时,索引页无法使用。如果查询字符串的第一个字确定,则可以使用索引。

Bitmap 索引

bitmap 索引适用于键值大量重复的列的查询,bitmap 索引对索引列的每一个键值分别索引,对于一个键值,可能分成一到多个范围进行存储。

每个键值的存储范围大致包括以下几个部分:首先是索引的键值,接着存放当前范围的起始 row id 和终止 row id,最后是这个键值在这个范围内的位置编码。将这个十六进制编码转化为二进制后,编码值是 1 的代表记录符合索引的键值,是 0 则表示不符合。由于保存了起始和终止的 row id 以及在这个范围内的位置变化,因此通过转换, bitmap 索引也可以对应到 row id。所以,bitmap 索引可以提供和 B-Tree 索引相同的功能。

bitmap 索引的特点

  1. bitmap 索引比 B 树索引要节省空间。因为 B 树索引要保存表中所有键值非空记录的 row id,而 bitmap 索引采用分段记录的方法,不会记录全部的 row id,而是只记录一个范围的起始地址和终止地址。

bitmap 存储空间大小由以下特点决定:

  • 表中总的记录的大小
  • 索引列的键值多少,因为 bitmap 索引对不同的键值分别存储,因此索引列的键值越多,所要占用的存储空间也就越多。
  • 操作的类型(批量或单条 记录操作)。
  • 相同键值记录的分布。如果相同键值的记录在物理分布上较为分散,那么在索引时可能会放到两个范围中。与前三者相比,这点对占用空间的影响要小得多。
  1. bitmap 索引建立的速度比较快
    B 树索引在建立时需要排序、定位等复杂的操作;而 bitmap 索引不需要排序,而且占用存储空间也较少。

  2. 基于规则的优化器无法使用 bitmap 索引索引
    只有基于代价的优化器才会利用 bitmap 索引。

  3. bitmap 索引存储 NULL 值
    对 NULL 进行判断的查询可以使用 bitmap 索引。由于存储 NULL 值,所以在计算表中的记录总数时,会优先使用 bitmap 索引。

即使表中包含了主键,在执行 select count(*) 操作时,仍然会优先使用 bitmap 索引。

  1. 通过 bitmap 索引访问表记录
    bitmap 索引更适合计算记录总数,即 select count(*) 操作,这是由 bitmap 索引的结构造成的。由于 bitmap 索引中没有存储每个键值对应的 row id ,所以在访问表中的记录时,Oracle 必须使用内部函数,通过起始 row id 和 终止 row id,以及索引键值在这个范围内位置的编码计算出这个记录的实际物理地址(row id)。而 select count(*)操作,Oracle 通过累计编码就可以得到相应的值,省去了映射到实际 row id 的操作的开销。

当 where 后面跟多个限定条件时,bitmap 索引可以发挥出更大的作用。除了 bitmap joib 索引外,bitmap 索引基本上都是单列索引。当对多个 bitmap 索引进行限定时,Oracle 可以利用 bitmap and 和 bitmap or 操作,在读取数据前就把不需要的数据过滤掉。这种操作正是 bitmap 索引的优势所在。

  1. bitmap 索引对批量 DML 操作只需要索引一次
    bitmap 索引对批量操作进行了优化,它会在这一批操作后,统一对数据进行一次索引。维护 bitmap 索引所花费的时间主要取决于 DML 语句操作的次数,而与 DML 语句每次修改的记录数无关。

由于 bitmap 索引结构,插入、删除或修改一条记录都有可能导致原有索引的重构。因此 bitmap 索引不适用于频繁变化的列。

  1. bitmap 索引的锁机制
    如果删除了一条记录,那么不仅仅锁住这一条记录,而是锁定 bitmap 索引中与这条记录处于同一个索引范围中的所有记录。

对于建立了 bitmap 索引的表,锁的最小粒度变为 bitmap 索引的范围。

在建立 bitmap 索引后要注意三点,第一点是批量操作,减少维护 bitmap 索引的代价;第二点是在操作结束后马上提交,减少对表的锁定,同事应经常注意 v$lock 视图,检查包含 bitmap 索引的表是否经常被锁;最后一点是注意收集统计信息,只有使优化器得到正确的信息,它才能做出正确的判断。


欢迎关注我的微信公众号: coderbee笔记,可以更及时回复你的讨论。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据