在位图索引中,数据库为每个索引键存储一个位图。在传统的B-树索引中,一个索引条目指向单个行。在位图索引中,每个索引键存储指向多个行的指针。
位图索引主要用于数据仓库,或在以特定方式引用很多列的查询环境中。可能需要一个位图索引的情况包括:
•索引列的基数较低,也就是说,不同值的数目相比表的总行数很小。
•被索引的表是只读的,或DML语句不会对其进行重大修改。
位图中的每一位对应于一个可能的rowid。如果设置了某位,那么与其相应的rowid行包含该键值。映射函数将位的位置转换为一个实际的rowid,所以,虽然位图索引使用不同的内部表示形式,但它提供了与B-树索引相同的功能。
如果更新了某个单行中的索引列,那么数据库将锁定整个索引键条目(例如M或F),而不只是该位映射到的更新行。因为一个键指向多个行,DML通常会锁定索引数据的所有这些行。因此,位图索引并不适合许多OLTP应用程序。
单表的位图索引
示例3-4显示了对sh.customers表的查询。此表中的某些列是创建位图索引的候选对象。
示例3-4客户表查询

cust_marital_status和cust_gender列的基数较低,而cust_id和cust_last_name列的基数较高。因此,在cust_marital_status和cust_gender列上创建位图索引可能是恰当的。而在其它列上创建位图索引则可能没什么用处。相反,在这些列上创建B-树唯一索引可能会提供最有效的表示形式和检索性能。
表3-2说明了示例3-4中所示的cust_gender列的位图索引。它包括两个分别针对每个性别的单独位图。

映射函数将位图中的每一位转换为客户表中的一个rowid。每一位的值取决于表中的相应行中的值。例如,M值的位图其第一位包含1,因为客户表的第一行的性别是M。对于位图cust_gender=‘M’,与第2、6,7行中相应的位为0,因为这些行上包含的值不是M。
注意:
与B-树索引不同,位图索引可以包括完全由空值组成的键。对空值建立索引对于某些的SQL语句是有用的,比如使用COUNT聚合函数的查询。
调查客户的人口趋势的分析人员可能会问,"我们的女性客户中,有多少是单身或离婚的?"这一问题对应于以下的SQL查询:

位图索引可以高效地处理此查询,通过计算得到的位图作为插图表3-3在1值的数量。要确定满足条件的客户,数据库可以访问表使用得到的位图。

位图索引可以有效地合并与WHERE子句中的多个条件相对应的索引。满足一些但不是全部条件的行,将在表本身被访问之前被过滤掉。这种技术往往大大提高了响应的时间。
位图联接索引
位图联接索引是建立在两个或更多表的联接之上的位图索引。对于表列中的每个值,索引存储被索引表中的相应行的rowid。相比之下,在标准位图索引中,索引是建立在一个表上的。
通过在联接前预先执行限制条件,位图联接索引是减少数据量的有效方式。举一个可能会用到位图联接索引的示例,假定用户经常查询某种特定职位类型的雇员数。一个典型的查询可能如下所示:

上述查询通常使用jobs.job_title上的一个索引来检索职位表中的Accountant行,然后通过(公共列)职位ID,和员工表中employees.job_id列上的索引来找到匹配的行。若要从索引本身检索数据,而不是从表中扫描,您可以创建一个位图联接索引,如下所示:

如图3-2,索引键是jobs.job_title,而被索引的表是employees。
图3-2位图联接索引

从概念上讲,employees_bm_idx是建立在示例3-5(包括示例输出)所示的SQL查询中的jobs.title列上的索引。在索引中的job_title键指向雇员表中的行。对会计师数目的查询可以仅使用索引,而不用访问employees表和jobs表,因为该索引本身已包含所请求的信息。
例3-5员工表和职位表的连接

在数据仓库中,连接条件是在维度表主键列和事实数据表的外键列之间的一个等值连接(使用相等运算符)。位图联接索引有时比物化视图的存储效率高得多,这是一种替代提前物化连接的方法。
位图存储结构
Oracle数据库使用一个B-树索引结构来为每个索引键存储位图。例如,如果jobs.job_title是一个位图索引的键列,那么索引数据存储在一个B-树中。单个位图存储在叶块中。
假定jobs.job_title列具有ShippingClerk、StockClerk、及其他几个唯一值。此位图索引的索引条目具有以下组件:
•作为索引键的职位
•一个rowids范围的低值rowid和高值rowid
•在该范围内的特定rowids的位图
从概念上讲,该索引中的一个索引叶块,可能包含如下所示的条目:

同一职位可能出现在多个条目中,这是因为其rowid范围不同。
假定某个会话更新了一名雇员的职务ID,从ShippingClerk到StockClerk。在这种情况下,该会话需要对旧值(ShippingClerk)和新值(StockClerk)所在索引键条目的独占访问权限。直到UPDATE提交之前,Oracle数据库会锁定这两个条目所指向的所有行,而不是由Accountant或其他任何键所指向的行。
位图索引的数据存储在一个段中。Oracle数据库将每个位图存储在一个或多个片断中。每个片断占一个单一数据块的一部分。




