代码之家  ›  专栏  ›  技术社区  ›  Moeb

位图索引有何帮助?

  •  29
  • Moeb  · 技术社区  · 15 年前

    Wikipedia 给出这个例子

    Identifier    Gender         Bitmaps
                                  F    M
    1           Female            1    0
    2           Male              0    1
    3           Male              0    1
    4           Unspecified       0    0
    5           Female            1    0
    

    但我不明白。

    • 首先,这是一个怎样的索引?索引是否应该指向给定键的行(使用rowid)?
    • 在这些索引有用的地方,典型的查询是什么?它们如何优于B树索引?我知道如果我们在 Gender 在这里,我们会得到很多结果,例如,如果我们寻找 Gender = Male ,需要进一步过滤掉(所以不是很有用)。位图如何改善这种情况?
    3 回复  |  直到 15 年前
        1
  •  35
  •   Patrick Marchand    15 年前

    如果上面给出了示例,则更好地表示位图索引:

    Identifier    Gender          RowID
    1             Female          R1
    2             Male            R2
    3             Male            R3
    4             Unspecified     R4
    5             Female          R5
    

    gender列上的位图索引(概念上)如下所示:

    Gender       R1    R2   R3   R4   R5
    Female       1     0    0    0    1
    Male         0     1    1    0    0
    Unspecified  0     0    0    1    0
    

    当一列中不同值的数目相对较低时,使用位图索引(考虑所有值都唯一的相反情况:位图索引将与每行一样宽, 只要让它有点像一个大的单位矩阵。)

    因此,有了这个索引,像

    SELECT * FROM table1 WHERE gender = 'Male'
    

    数据库在索引中查找性别值的匹配项,查找位设置为1的所有行ID,然后转到并获取表结果。

    类似的查询:

    SELECT * FROM table1 WHERE gender IN ('Male', 'Unspecified')
    

    会得到1位的男性,1位的未指定,做一个位或然后去得到结果位为1的行。

    因此,与B*树索引相比,使用位图索引的优势在于存储(基数较低,位图索引非常紧凑),以及在解析实际的行ID之前执行逐位操作的能力,这可以非常快。

    请注意,位图索引可能会对插入/删除产生性能影响(概念上,在位图中添加/删除一列,然后相应地重新对其进行调整…),并且可能会产生大量争用,因为一行上的更新可以锁定整个对应的位图项目,并且在之前,您不能更新不同的行(具有相同的位图值)。第一次更新已提交/回滚。

        2
  •  12
  •   Albin Sunnanbo    15 年前

    这样做的好处是,当对多个列进行筛选时,在实际选择数据之前,可以将相应的索引与按位操作合并。 如果你有性别,眼睛颜色,头发颜色 然后查询

    select * from persons where
                          gender = 'male' and 
                          (eye_colour = 'blue' or hair_colour = 'blonde')
    

    将首先在眼睛颜色[蓝色]指数和头发颜色[金色]指数之间进行位或,最后在结果和性别[男性]指数之间进行位或。这个操作在计算和I/O上都执行得非常快。
    生成的位流将用于选择实际行。

    位图索引通常用于数据仓库应用程序中的“星形连接”。

        3
  •  4
  •   David    15 年前

    正如维基百科文章所指出的,它们使用位操作,这比比较整数等数据类型执行得更好,因此简短的答案是提高查询速度。

    从理论上讲,从你的例子中选择所有男性或所有女性应该花费更少的计算和时间。

    想想这在引擎盖下是如何工作的,就应该明白为什么这样做更快。一个比特在逻辑上要么是真的要么是假的。如果您想使用WHERE子句进行查询,则最终会对记录的值进行判断,得出是真是假,以确定是否将它们包含在结果中。

    序言-剩下的就是外行的台词和非技术性的台词。

    所以下一个问题是,要评估什么才是真的?即使比较数值也意味着计算机必须…

    1. 为要计算的值分配内存
    2. 为控制值分配内存
    3. 将值赋给每个(将其计为两个步骤)
    4. 比较这两个-对于一个数字,这应该很快,但对于字符串,有更多的字节要比较。
    5. 将结果赋给0(假)或1(真)值。

    如果使用多部分WHERE子句,如WHERE“this=this and that=that”,则重复此操作。

    1. 对步骤5中生成的结果执行位操作
    2. 提出最终价值
    3. 取消分配步骤1-3中分配的内存

    但是使用位逻辑,您只需要查看0(假)和1(真)值。比较工作的90%开销被消除。