本文内容
索引的目的是,提供在表中指向包含一个给定键值的数据行。常规索引的实现是,为每个键存储一个对应这些键值数据航的 rowid 列表。Oracle 数据库反复地用已存储的 rowid 存储每个键值。在 Bitmap 索引中,使用每个键值的位图,而不是 rowid 列表。
位图中的每个比特对应一个可能的 rowid。若比特被设置,则意味着相应 rowid 的数据行包含该键值。映射函数可以把比特位转换成一个实际的 rowid,因此,bitmap 索引提供与常规索引相同的功能,即使它内部使用不同的表示。若不同的键值(不重复值)数量较小,则 bitmap 索引非常节省空间。
Bitmap 索引能有效地合并 WHERE 子句中符合很多条件的索引。在访问表本身之前,满足一些,而不是全部条件的行可以被过滤掉。通常会显著提高响应时间。
Bitmap 索引对数据仓库应用程序很有好处。数据仓库应用程序具有大量数据和 ad hoc 查询,但却是低水平的并发事务。对这样的应用程序,Bitmap 索引提供:
- 为大量 ad hoc 查询减少响应时间
- 与其他索引技术相比,大幅度减少了使用空间
- 即使在很低端的硬件上也能获得显著的性能
- 非常有效的并行 DML 和负载
用 B-tree 索引全面索引一个大表在空间上可能非常昂贵,因为,索引可能比表中的数据大很多倍。Bitmap 索引通常只有表中已索引数据大小的一部分。
Bitmap 索引不适合具有大量并发事务、修改数据的 OLTP 应用程序。该索引主要用于在数据仓库应用程序中的决策支持,这些用户通常都是查询,而不是更新。
Bitmap 索引也不适于用小于或大于比较查询的那些列。例如,salary 列,它出现在 WHERE 子句与某个值比较用 B-tree 索引最好。bitmap 索引只对等值查询很有用,特别是结合 AND、OR 和 NOT 运算符。
Bitmap 索引与 Oracle 数据库优化器和执行引擎集成。它们可以无缝地与其他 Oracle 数据库的执行方法结合使用。例如,优化器可以决定在两个之间执行一个 hash 连接,一个表使用 Bitmap 索引,而另一个使用常规 B-tree 索引。优化器会将考虑 Bitmap 索引和其他可用的访问方法,如常规 B-tree 索引和全表扫描,并选择最有效的方法,在适当情况下考虑并行。
用 bitmap 索引并行查询和并行 DML 与传统索引一样。分区表上的 bitmap 索引必须是本地索引。还支持并行创建索引和连接索引。
在低基数列上使用 bitmap 索引能获得最大的优势:也就是说,列上不重复值的数量与表中行数相比很小。若一个列不重复值的数量小于表中行数的 1%,或一个列中的值重复超过 100 次以上,则可以考虑为该列创建 bitmap 索引。如果列涉及复杂查询,即使该列具有低重复,高基数,也可以创建 bitmap 索引。
例如,一个有 100 万行的表,某个列具有 10000 个不重复的值,那么就可以为该列创建 bitmap 索引。该列的 bitmap 索引性能会超过 B-tree 索引,特别是当该列通常与其他列连接查询。
B-tree 索引对于高基数列最有效:也就是说,数据具有很多可能值,例如 CUSTOMER_NAME 或 PHONE_NUMBER 这样的列。在某些情况下,一个B-tree 索引会比已索引的数据大。若适当使用,bitmap 索引会显著比相应的 B-tree 索引小。
在 ad hoc 查询和类似情况下,bitmap 索引可以显著提高查询性能。AND 和 OR 条件,在把结果 bitmap 转换成 rowid 前,通过在 bitmap 索引上执行相应的布尔操作,可以被快速解析。如果结果行数较小,那么查询会很快返回,无需全表扫描。
表 1 是 customer 表的部分数据。
表 1 Bitmap 索引示例
CUSTOMER # | MARITAL_ STATUS | REGION | GENDER | INCOME_ LEVEL |
101 | single | east | male | bracket_1 |
102 | married | central | female | bracket_4 |
103 | married | west | female | bracket_2 |
104 | divorced | west | male | bracket_4 |
105 | single | central | female | bracket_2 |
106 | married | central | female | bracket_3 |
MARITAL_STATUS、REGION、GENDER 和 INCOME_LEVEL 都是低基数列。MARITAL_STATUS 和 REGION 列只有三个可能的值;GENDER 是两个;INCOME_LEVEL 有四个。因此,在这些列上创建 bitmap 索引很合适。不能在 CUSTOMER# 列创建 bitmap 索引,因为,该列是高基数列。相反,在该列上使用唯一 B-tree 索引更有效的。
图 2 说明 REGION 列上的 bitmap 索引。它由三个独立位图组成,每个区域是位图中的一个。
表 2 Sample Bitmap
REGION='east' | REGION='central' | REGION='west' |
1 | 0 | 0 |
0 | 1 | 0 |
0 | 0 | 1 |
0 | 0 | 1 |
0 | 1 | 0 |
0 | 1 | 0 |
位图中的每个条目或比特对应 CUSTOMER 表的一行。每个比特位的值取决于表中对应行的值。例如,位图 REGION='east' 包含一个,第一个比特位为 1。这是因为它是 CUSTOMER 表的第一行。位图 REGION='east' 其他比特位为 0,这是因为表中没有其他行为 east。
一位调查人口的分析师,可以问,“我们已婚客户中有多少人居住在中部或西部区域?”,相当于下面 SQL:
SELECT COUNT(*) FROM CUSTOMER
WHERE MARITAL_STATUS = 'married' AND REGION IN ('central','west');
Bitmap 索引可以高效处理这个查询,如下图所示。若确定满足条件的员工,可以使用如下结果位图来访问表:
图 1 使用 Bitmap 索引执行查询
说明:图 1 的计算过程就是相应的比特位做运算。
不同于其他大多数索引类型,Bitmap 索引可以包含 NULL 值的那些行。null 索引对于某些 SQL 语句很有用,例如用聚合函数 COUNT 查询。
像其他索引,你在分区表上创建 bitmap 索引。唯一的限制是 bitmap 索引必须是对本地的分区表——它们不能使全局索引。全局 bitmap 索引只被非非分区表支持。