背景:

按照《Oracle Conecpt》的结构一起了解Oracle数据库,这是学习Oracle从入门到精通的基础。



本文主题:第三章《Indexes and Index-Organized Tables》 - Overview of Indexes。


反向索引

反向索引也是一种B-树类型的索引,和普通B-树索引不同的是,他会在物理层上将每个索引键值的字节逆序排列。例如,如果索引键值是20,在标准B-树索引中,十六进制存储的两个字节是C1和15,对于反向索引,他存储的就是15和C1。


反向索引能解决B-树索引最右侧叶子块争用的问题。在Oracle RAC架构下尤其明显,因为多个实例会反复修改相同的数据块。例如,orders表中主键是序列,递增顺序。集群中的一个节点上主键值增加到20,另一个节点增加到21,每个实例都要将他的值写入到索引最右侧同一个叶子块中,此时就会产生了争用。


在反向索引中,字节顺序的反转会让插入操作发生在索引的所有叶子键值上。例如,键值20和21在标准B-树索引中可能是相邻存储的,然而在反向索引中,他们会存储在不同的数据块中。因此,这种递增顺序的键值插入所消耗的I/O就会更加平均。


由于反向索引的数据不是按照列的顺序存储的,因此在某些场景下就无法支持索引范围扫描的检索。例如,一个用户需要检索ID值大于20的记录,数据库就无法从包含20这个ID值的索引叶子块水平移动进行检索。


换句话说,反向索引的副作用,要清楚才行,如果应用大多数查询是检索“最近的”数据,通常只需要缓存整个索引很少的一部分,对于反向索引,他的目的是将热点从索引最右侧叶子块,分配到索引不同的区域,因此可能需要缓存索引的大部分块,才能达到和反转之前相同的缓存效果。


如图,这是普通B-树索引,101-105可能存储在索引最右侧一个叶子块,

《Oracle Concept》第三章 - 8_键值


改成反向索引的,此时101-105可能位于不同的索引叶子块,虽然不存在最右侧叶子块的争用了,但是相同的范围检索条件,可能消耗更多的I/O,

《Oracle Concept》第三章 - 8_Database_02


针对这种场景,散列分区索引,可能是另一种解决方案,《一个索引热块的性能问题》,就介绍了一个相关的问题。


可以参考:

《Oracle Database Performance Tuning Guide》了解关于反向索引设计的考虑。