B+树索引是是目前关系型数据库系统中查找最为常用和最为有效的索引,B+树的索引构造类似于二叉树,根据键值(key Value)快速找到数据。
1、什么是B+树?
首先,B+树中的B并不是二叉树(binary)的意思,这里的B表示的是blance即平衡的意思。那么B+树其实就是平衡查找树。其满足两个条件:平衡树和查找树。
关于平衡树的定义我们可以再任何一个数据结构书上找到,最常用的莫过于平衡二叉树,其定义为满足任何节点的两个子树的高度最大差为1.如下图所示,左边的为非平衡二叉树,右边的为平衡二叉树。
对于查找树,大家应该都知道二分查找,二分查找平均查找时间为O(n)=logn。之所以查找如此之快是因为其中的数据已经得到排序。同理二叉查找树也是经过排序的查找树。其定义为任何一个非叶子节点的左子树的值不大于父节点的值,右子树的值大于其父节点的值。
对于一个已经排序的数组,将其构造成二叉查找树的形式有很多种,但是效率最高的一种就是平衡二叉查找树。我们用的B+树就是这样的平衡查找树,只不过其为普通的树而非二叉树。
上图为一个深度为2的B+树,其所有的记录都是存放在最下层的叶子节点上的。而父节点只是提供了查找该叶子节点的索引。如果我们需要查找一个记录,根据B+树可以很快地定位到该记录:例如我们如果要查找15,我们先通过第一层索引找到25,比较15与25,由于15小于25所以我们在25所指向的叶子节点区域查找15,这样就可以很快地定位到15这条记录。
在MySQL的InnoDB引擎中,B+树索引就是按照上述方式存储数据的。至于其插入和删除操作,感兴趣的可以参考这方面的专业书籍。
2、B+树索引
B+树索引的本质就是B+树在数据库中的实现。B+树在数据库中有一个特点就是高扇出性,在数据库中B+树一般都在2-4层,因此查找某一键值记录时最多只需要2-4次IO。
在数据库中B+树索引可分为聚集索引(clustered index)和辅助索引(secondary index)。不管是辅助索引还是聚集索引,其在数据库内部都是B+树。聚集索引与辅助索引不同的是聚集索引在叶子节点存放着记录一整行的信息。
1、聚集索引:聚集索引就是按照每张表的主键构造一颗B+树,同时叶子节点中存放着的即为整张表的行记录数据。一般情况下,查询优化器更倾向于采用聚集索引,因为其叶子节点中存放着整个表的记录。由于每张表都只有一个主键(无论是用户指定还是数据库自动创建的),所以每张表都会生成一个B+数聚集索引,而且只有一个。相反,我们可以为一张表指定多个辅助索引。
建立如下数据库:
create table t (
a int not null,
b int,
c int,
primary key (a)
)engine=innodb;
在书库库t中我们指定主键为a,则数据库会自动按照a的值构建B+树索引。B+树索引的一个好处就是它对于主键的排序查找和范围查找非常快。我们在表t中插入如下数据:
insert into t select 4,1,8;
insert into t select 5,4,7;
insert into t select 2,3,4;
insert into t select 8,4,9;
insert into t select 7,2,3;
insert into t select 1,3,3;
insert into t select 3,6,5;
insert into t select 10,8,6;
insert into t select 9,9,1;
insert into t select 6,7,2;
insert into t select 9,9,1;
insert into t select 6,7,2;
对其进行查找和排序:
如图所示:第一张是按照主键a进行排序,其基本在一瞬间就可以完成,第二张是按照b排序,则其花费时间比按照主键排序要多。
2、辅助索引:对于辅助索引,叶子节点并不包含行记录的所有数据。叶子节点除了包含键值以外,每个叶子节点中的索引行中还包含了一个
书签。该书签用来告诉InnoDB存储引擎哪里可以找到与索引相对应的行数据。由于InnoDB存储引擎表是索引组织表,因此InnoDB存储引擎的辅助索引的书签就是相应行数据的聚集索引键。
上图所示为辅助索引与聚集索引的关系,助索引的叶子节点中存储的为聚集索引的键值,要想通过辅助索引获得一个完整的记录,InnoDB引擎会遍历辅助索引从而查到其对应叶子节点所指向聚集索引的主键,然后根据该主键通过聚集索引获得一个完整的记录。
假设一张表中辅助索引的高度为3,聚集索引的高度也为3,则通过辅助索引获得一个行记录的要经过6此查找,其中前三次查找在在辅助索引中找到对应的聚集索引中的键值,后三次是根据查找得到的键值在聚集索引中找到完整行。