5 Indexes and Index-Organized Tables
Overview of Bitmap Indexes
位图索引概述
在位图索引中,数据库为每个索引键存储一个位图。在传统的B树索引中,一个索引条目指向单个行。在位图索引中,每个索引键存储指向多个行的指针。
位图索引主要用于数据仓库,或者查询以一种特定方式引用许多列的环境中。可能需要使用位图索引的情况包括:
- 索引列的基数很低,即不同值的数量与表行数相比很小。
- 索引表是只读的,或者不会受DML语句进行重大修改的影响。
以数据仓库为例,sh.customers表有一个cust_gender列,只有两个可能的值:M和F。假设特定性别客户数量的查询很常见。在这种情况下,customers.cust_gender列可能适合使用位图索引。
位图中的每一位对应于一个可能的rowid。如果设置了该位,那么具有相应rowid的行包含该键值。一个映射函数将位的位置转换为实际的rowid,因此尽管位图索引使用不同的内部表示形式,但它提供与B树索引相同的功能。
如果单行中的索引列被更新,则数据库会锁定整个索引键条目(例如,M或F),而不只是锁定映射到更新行的单独位。由于一个键指向多行,对索引数据的DML通常会锁定所有这些行。因此,位图索引不适用于许多OLTP应用程序。
-
示例:单表上的位图索引
在此示例中,sh.customers表的某些列适合使用位图索引。 -
位图连接索引
位图连接索引是用于两个或多个表连接的位图索引。 -
位图存储结构
Oracle数据库使用B树索引结构来存储每个索引键的位图。
另请参阅:
- Oracle Database SQL Tuning Guide 以了解更多关于位图索引的信息
- Oracle Database Data Warehousing Guide 以了解如何在数据仓库中使用位图索引
Example: Bitmap Indexes on a Single Table
示例:单表上的位图索引
在这个示例中,sh.customers表的一些列适合使用位图索引。
考虑以下查询:
SQL> SELECT cust_id, cust_last_name, cust_marital_status, cust_gender
2 FROM sh.customers
3 WHERE ROWNUM < 8 ORDER BY cust_id;
| CUST_ID | CUST_LAST_NAME | CUST_MARITAL_STATUS | CUST_GENDER |
|---------|----------------|---------------------|-------------|
| 1 | Kessel | M | |
| 2 | Koch | F | |
| 3 | Emmerson | M | |
| 4 | Hardy | M | |
| 5 | Gowen | M | |
| 6 | Charles | single | F |
| 7 | Ingram | single | F |
7 rows selected.
cust_marital_status和cust_gender列的基数很低,而cust_id和cust_last_name的基数很高。因此,cust_marital_status和cust_gender上可能适合使用位图索引。对于其他列,位图索引可能不太有用。相反,在这些列上使用唯一B树索引可能会提供最有效的表示形式和检索。
表5-4展示了前面示例中所示的cust_gender列的位图索引示例。它包含两个单独的位图,分别用于每个性别。
表5-4 单列的位图示例
Value | Row 1 | Row 2 | Row 3 | Row 4 | Row 5 | Row 6 | Row 7 |
---|---|---|---|---|---|---|---|
M | 1 | 0 | 1 | 1 | 1 | 0 | 0 |
F | 0 | 1 | 0 | 0 | 0 | 1 | 1 |
一个映射函数将位图中的每一位转换为customers表的rowid。每个位的值取决于表中相应行的值。例如,M值的位图中的第一位为1,因为customers表的第一行的性别为M。cust_gender='M’的位图在行2、6和7的位上为0,因为这些行的值不为M。
注意:
与B树索引不同,位图索引可以包含完全由空值组成的键。对空值建立索引对某些SQL语句很有用,比如带有聚合函数COUNT的查询。
一位分析师在调查客户的人口统计趋势时可能会问:“我们有多少女性客户是单身或离婚的?”这个问题对应以下SQL查询:
SELECT COUNT(*)
FROM customers
WHERE cust_gender = 'F'
AND cust_marital_status IN ('single', 'divorced');;
位图索引可以通过计算结果位图中值为1的数量来高效处理这个查询,如表5-5所示。为了识别满足条件的客户,Oracle数据库可以使用结果位图来访问表。
表5-5 两列的位图示例
Value | Row 1 | Row 2 | Row 3 | Row 4 | Row 5 | Row 6 | Row 7 |
---|---|---|---|---|---|---|---|
M | 1 | 0 | 1 | 1 | 1 | 0 | 0 |
F | 0 | 1 | 0 | 0 | 0 | 1 | 1 |
single | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
divorced | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
single or divorced, and F | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
位图索引高效地合并与WHERE子句中多个条件相对应的索引。在表本身被访问之前,满足一些条件但不是所有条件的行会被过滤掉。这种技术提高了响应时间,通常很显著。