
理解位图索引( 2 003-09 )
位图索引对于特定类型的应用是一个巨大的福音。但是,在这个领域中有许多关于位
图索引如何工作,何时使用它们以及它的副作用的错误信息。本文测试了位图索引的
结构,并尝试解释一些很常见的错误概念是如何产生的。
大家都知道的 …
如果你进行一个快速的关于人们对位图
索引认知的调查问卷,你可能发现以下
说法竟然被频繁引用:
a)
当在有位图索引的表上发生更新
时,会持有全表锁。
b)
位图索引适用于低基数列。
c)
即便要返回表的大部分,位图索
引也要比表扫描更有效。
第三种说法实际上是第二种说法的一个
推论(未经测试),而且,所有这三种
说法都处于错误和极易导致误信的灰色
地带。
当然,这些说法有一些接近真相的部分
—这足以解释它们为什么会出现在如此
重要的位置。
本文的目的是去测试位图索引的结构,
回顾上述说法,并尝试整理出一些使用
位图索引时的成本和收益。
什么是位图索引 ?
为了更有效的找到请求的行,索引被创
建了。位图索引也不例外—然而位图索
引背后的策略与 B*tree 索引背后的策略
是非常不同的。为说明这一点,我们可
以从检查几个转储块开始。
考虑图 1 中的 SQL 脚本:.
注意我们定义了 btree_col 和
bitmap_col
,
以便我们可以有相同的从
0 到 9 循环出现的数据
在一个块尺寸为 8K 的 9.2 数据库上,
得到的结果表占用了 882 个块。B*tree
索引有 57 个叶子块, 位图索引有 10 个
叶子块。
显然位图索引比 B*tree 索引在某种程度
上封装得更紧实。为了观察封装,我们
使用类似如下的命令生成符号转储:
alter system
dump datafile x block y;
结果如图 2 所示—小心,转储块的结果
可能导致一个小误解。部分显示的信息
是推导出来的,部分为了清晰起见而进
行了重新排列。
位图会锁表吗?
观察图 2,我们看到 B*tree 索引的每个
条目是由 flags, lock byte, 和两列数据
(本例中如此)构成的。这两列实际上
是索引值和 ROWID。表中的每一行在
索引中都有对应的一个条目。 (如果索
Extract from B*tree leaf
row#538[2016] flag: -----, lock: 0
col 0; len 2; (2): c1 02
col 1; len 6; (6): 00 40 c5 7d 00 09
row#539[2004] flag: -----, lock: 0
col 0; len 2; (2): c1 02
col 1; len 6; (6): 00 40 c5 7d 00 13
Extract from bitmap leaf
row#2[4495] flag: -----, lock: 0
col 0; len 2; (2): c1 03
col 1; len 6; (6): 00 40 c5 62 00 00
col 2; len 6; (6): 00 40 c7 38 00 1f
col 3; len 3521; (3521):
cb 02 08 20 80 fa 54 01
04 10 fb 53 20 80 00 02
fc 53 04 10 40 00 01 fa
53 02 08 20 fb 53 40 00 . . .
Figure 2: Symbolic block dumps.
create table t1
nologging
as
select
rownum id,
mod(rownum,10) btree_col,
mod(rownum,10) bitmap_col,
rpad('x',200) padding
from
all_objects
where rownum <= 30000
;
create index t1_btree on
t1(btree_col);
create bitmap index t1_bit on
t1(bitmap_col);
Figure 1 Sample data.
评论