Oracle通过位图索引提高查询效率

网络整理 - 07-27

  众所周知,索引可以在很大程度上提高数据库的查询效率。但是如果索引使用不当,如在不恰当的地方采用了不恰当的索引,那么反而会起到适得其反的效果。如下图所示的表,该采用什么索引呢?笔者借这个机会,跟大家讨论一下位图索引的使用时机以及注意事项。

  众所周知,索引可以在很大程度上提高数据库的查询效率。但是如果索引使用不当,如在不恰当的地方采用了不恰当的索引,那么反而会起到适得其反的效果。如下图所示的表,该采用什么索引呢?笔者借这个机会,跟大家讨论一下位图索引的使用时机以及注意事项。

  一、 B树索引的缺陷

  在实际工作中,B树索引是Oracle数据库中最常用的一种索引。如在使用Create Index语句创建索引的时候,默认采用的就是B树索引。在B树索引中,是通过在索引中保存排序过的索引列以及其对应的Rowid列的值来实现的。不过对于某些比较特殊的情况,如基数比较小的列,使用这个B树索引反而会降低数据库的查询效率。

  基数在Oracle数据库中指的是某个列可能拥有的不重复数值的个数。如上图为例,SEX指员工的性别,一般就只有男女两个值(其中1代表男、0代表女),其基数就为2。假设企业要组织公司所有的女员工出去旅游,作为三八妇女节的礼物。为此就需要查询出公司所有女员工的信息。此时如果在性别列上加入B树索引,那么反而会得到适得其反的效果。查询效率不但没有提升,反而下降。

  在这些基数比较小的列上创建B树索引并对其进行查询的话,系统就会返回大量的记录。因而这并不是具有高度选择性的索引,并不能够显着提高查询的速度。当然并不是说B树索引不好,而是指其没有用对地方。

  二、 位图索引的特点以及使用时机

  在数据库中(包括Sql Server数据库),对于这种基数比较小的列,如果只有有限的几个固定值,如上表中的性别、婚姻状况等等,要为其建立索引的话,采用的就应该是位图索引,而不是B树索引。

  位图索引为什么可以提高基数比较小的表的查询速度呢?这主要是因为在创建位图索引的时候,数据库往往会对整个表进行扫描,并未索引列的每个取值建立一个位图(位图索引的名字也由此而来)。在这个位图中,为表中的每一行使用一个位元来表示该行是否包含该位图的索引列的取值。位元到行的ROWID的对应关系通过位图索引中的应收函数来完成。如此的话,位图索引就能够以一种完全不同的内部机制来完成与B树索引相同的功能。

  另外值得一提的是,对于B树索引而言,如果在查询条件语句中采用了AND等操作符号,其查询的效率会大打折扣。故在数据库优化中,会建议大家不要使用这些操作符,改用其他操作符代替。不过如果采用位图索引的话,则没有这方面的顾虑。如上例所示,假设用户需要查找已婚的女性,那么就可以使用如下的语句查询。

  select t.*, t.rowid

  from userinfo t

  where t.merital=’已婚’ and t.sex=0

  这个查询引用了一些创建了位图索引的列时,这些位图可以很方便的与AND或者OR操作符结合以找出想要的数据。数据库在后台处理的时候,先利用已经创建的位图进行逻辑运算,然后计算结果位图中1的个数,就可以查询到满足条件的所有记录。如果查询到结果后还需要更改数据的话,那么只需要按照结果位图中取1的位元对应的ROWID列的值进行映射即可。

  三、 位图索引的使用限制

  位图索引虽然在某些情况下能够起到比B树索引更好的效果。但是需要注意的是,并不是在任何场合都有效。如上例所示,如果在员工编号或者员工姓名列中使用的话,反而会降低数据查询的效率。故其使用仍然受到比较大的限制。如上面列举的案例,一般情况下只有在“基数比较小的列中”和“需要使用与和或的运算中”采用位图索引能够起到比B树索引更好的效果。其他情况还是使用B数索引或者函数索引为好。

  在Oracle数据库中,有B树索引、位图索引、函数索引等等。具体采用哪种索引,还是要根据不同的情形来对待。随着数据库应用越来越复杂,单靠一个B树索引已经不能够应付了。如列中包含了表达式或者函数的话,B树索引或者位图索引都不能够用,只有用函数索引。对于数据库专家来说,索引的创建与管理或许没有难度,只需要简单的几个语句即可。比较困难的是,如何根据实际情况来选择合适的索引