-
B-tree的来源
是为磁盘存储而专门设计的一类平衡搜索树,它可以降低磁盘I/O操作。假如用平衡二叉树来查找,100条数据,根据平衡二叉树公式(深度为n,最多有2ⁿ-1个结,20+21+22+23…+2(n-1)=(2n)-1=1000000,得出n为20)查找100w条数据中的一个数据时最多需要20次磁盘IO,20次磁盘IO,这个性能对于磁盘来说太慢了。B-tree每层上可以容纳更多的节点,可以减少树的高度,从而减少磁盘IO次数从而提高性能。
-
概念
B树,从名称我们可以联想到二叉树,它是二叉树的演化版。相比于二叉树,B树允许节点可以有两个以上的子节点。这种结构维护有序数据并允许对数进行搜索,顺序访问,插入和删除。
定义:
2.1.B-tree树
1. 每个节点最多只有m个子节点。
2. 每个非叶子节点(除了根)具有至少⌈ m/2⌉子节点。
3. 如果根不是叶节点,则根至少有两个子节点。
4. 具有k个子节点的非叶节点包含k -1个键。
5.所有叶子都出现在同一水平,没有任何信息(高度一致)。
图为B-tree结构
2.2. B+tree树
1.有k个子树的中间节点包含有k个元素(B树中是k-1个元素),每个元素不保存数据,只用来索引,所有数据都保存在叶子节点。
2.所有的叶子结点中包含了全部元素的信息,及指向含这些元素记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接。
3.所有的中间节点元素都同时存在于子节点,在子节点元素中是最大(或最小)元素。
图为B+tree结构
2.3 B-tree和B+tree的区别
1)非叶子节点只存储键值信息。
2)数据记录都存放在叶子节点中
3)B+tree的所有关键字存储在叶子节点,非叶子节点不存储真正的data。
4)B+tree为所有叶子节点增加了一个链指针。
5)B+tree支持叶子节点的延展性(横向性)
3.MySQL是如何使用B树的?
3.1innodb引擎机制:
//先创建一张数据表并插入数据
CREATE TABLE `test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` char(4) NOT NULL,
PRIMARY KEY (`id`),
KEY `index_name` (`name`)
);
insert test(id,name) values(1,'鼠');
insert test(id,name) values(2,'牛');
对于innodb来说,只有一个数据文件,这个数据文件本身就是用B+树形式组织,B+树每个节点的关键字就是表的主键,因此innodb的数据文件本身就是主索引文件,如下图所示,主索引中的叶子页(leaf page)包含了数据记录,但非叶子节点只包含了主键,术语“聚簇”表示数据行和相邻的键值紧凑地存储在一起,因此这种索引被称为聚簇索引,或聚集索引。
这种索引方式,可以提高数据访问的速度,因为索引和数据是保存在同一棵B树之中,从聚簇索引中获取数据通常比在非聚簇索引中要来得快。
所以可以说,innodb的数据文件是依靠主键组织起来的,这也就是为什么innodb引擎下创建的表,必须指定主键的原因,如果没有显式指定主键,innodb引擎仍然会对该表隐式地定义一个主键作为聚簇索引。
3.2 聚集索引 & 辅助索引
数据库中的B+Tree索引可以分为聚集索引(clustered index)和辅助索引(secondary index)。
上面的B+Tree示例图在数据库中的实现即为聚集索引,聚集索引的B+Tree中的叶子节点存放的是整张表的行记录数据。
辅助索引与聚集索引的区别在于:
辅助索引的叶子节点并不包含行记录的全部数据,而是存储相应行数据的聚集索引键,即主键。
当通过辅助索引来查询数据时,InnoDB存储引擎会遍历辅助索引找到主键,然后再通过主键在聚集索引中找到完整的行记录数据。
4.为什么mysql的索引使用B+树而不是B树呢??
(1)B+树更适合外部存储(一般指磁盘存储),由于内节点(非叶子节点)不存储data,所以一个节点可以存储更多的内节点,每个节点能索引的范围更大更精确。也就是说使用B+树单次磁盘IO的信息量相比较B树更大,IO效率更高。
(2)mysql是关系型数据库,经常会按照区间来访问某个索引列,B+树的叶子节点间按顺序建立了链指针,加强了区间访问性,所以B+树对索引列上的区间范围查询很友好。而B树每个节点的key和data在一起,无法进行区间查找。