mysql索引底层结构B树和B+树

1.为什么要用B+Tree实现

目前大多数数据库系统及文件系统都采用 B-Tree 或其变种 B+Tree 作为索引结构。B+ 树中的 B (balance)代表平衡,而不是二叉。B+ 树是从最早的平衡二叉树演化而来的。B+ 树是由二叉查找树、平衡二叉树(AVLTree)和平衡多路查找树(B-Tree)逐步优化而来。

二叉查找树:左子树的键值小于根的键值,右子树的键值大于根的键值。
AVL 树:平衡二叉树(AVL 树)在符合二叉查找树的条件下,还满足任何节点的两个子树的高度最大差为 1,但不是红黑树。
平衡多路查找树(B-Tree):为磁盘等外存储设备设计的一种平衡查找树。
那么纠结该如何选型呢?

索引的标准:IO渐进复杂度,说白了就是推演过程(每个节点都是1次IO),B+树是为磁盘及其他存储辅助设备而设计一种平衡查找树(不是二叉树),所有记录的节点按大小顺序存放在同一层的叶节点中,各叶节点用指针进行连接。

InnoDB 存储引擎使用页作为数据读取单位,页是其磁盘管理的最小单位,默认 page 大小是 16k。系统的一个磁盘块的存储空间往往没有这么大,因此 InnoDB 每次申请磁盘空间时都会是若干地址连续磁盘块来达到页的大小 16KB。在查询数据时如果一个页中的每条数据都能助于定位数据记录的位置,这将会减少磁盘 I/O 的次数,提高查询效率。

3.1 B-Tree
B-树是一种多路自平衡的搜索树 它类似普通的平衡二叉树,不同的一点是B-树允许每个节点有更多的子节点。B-Tree 相对于 AVLTree 缩减了节点个数,使每次磁盘 I/O 取到内存的数据都发挥了作用,从而提高了查询效率。

注:B-Tree就是我们常说的B树,一定不要读成B减树,否则就很丢人了

那么m阶 B-Tree 是满足下列条件的数据结构:

所有键值分布在整颗树中
搜索有可能在非叶子结点结束,在关键字全集内做一次查找,性能逼近二分查找
每个节点最多拥有m个子树
根节点至少有2个子树
分支节点至少拥有m/2颗子树(除根节点和叶子节点外都是分支节点)
所有叶子节点都在同一层、每个节点最多可以有m-1个key,并且以升序排列

mysql索引底层结构B树和B+树_第1张图片
每个节点占用一个磁盘块,一个节点上有两个升序排序的关键字和三个指向子树根节点的指针,指针存储的是子节点所在磁盘块的地址。两个关键词划分成的三个范围域对应三个指针指向的子树的数据的范围域。以根节点为例,关键字为 17 和 35,P1 指针指向的子树的数据范围为小于 17,P2 指针指向的子树的数据范围为 17~35,P3 指针指向的子树的数据范围为大于 35。

模拟查找关键字 29 的过程:

根据根节点找到磁盘块 1,读入内存。【磁盘 I/O 操作第 1 次】
比较关键字 29 在区间(17,35),找到磁盘块 1 的指针 P2。
根据 P2 指针找到磁盘块 3,读入内存。【磁盘 I/O 操作第 2 次】
比较关键字 29 在区间(26,30),找到磁盘块 3 的指针 P2。
根据 P2 指针找到磁盘块 8,读入内存。【磁盘 I/O 操作第 3 次】
在磁盘块 8 中的关键字列表中找到关键字 29。
分析上面过程,发现需要 3 次磁盘 I/O 操作,和 3 次内存查找操作。由于内存中的关键字是一个有序表结构,可以利用二分法查找提高效率。而 3 次磁盘 I/O 操作是影响整个 B-Tree 查找效率的决定因素。

但同时B-Tree也存在问题:

每个节点中有key,也有data,而每一个页的存储空间是有限的,如果data数据较大时将会导致每个节点(即一个页)能存储的 key 的数量很小。
当存储的数据量很大时同样会导致 B-Tree 的深度较大,增大查询时的磁盘 I/O 次数,进而影响查询效率
3.2 B+Tree
B+Tree 是在 B-Tree 基础上的一种优化,InnoDB 存储引擎就是用 B+Tree 实现其索引结构。它带来的变化点:
mysql索引底层结构B树和B+树_第2张图片
B+树每个节点可以包含更多的节点,这样做有两个原因,一个是降低树的高度。另外一个是将数据范围变为多个区间,区间越多,数据检索越快
非叶子节点存储key,叶子节点存储key和数据
叶子节点两两指针相互链接(符合磁盘的预读特性),顺序查询性能更高
注:MySQL 的 InnoDB 存储引擎在设计时是将根节点常驻内存的,因此力求达到树的深度不超过 3,也就是说 I/O 不需要超过 3 次。

通常在B+Tree上有两个头指针,一个指向根节点,另一个指向关键字最小的叶子节点,而且所有叶子节点(即数据节点)之间是一种链式环结构。因此可以对 B+Tree 进行两种查找运算:一种是对于主键的范围查找和分页查找,另一种是从根节点开始,进行随机查找。

3.3 B-树和B+树的区别
B+树内节点不存储数据,所有数据存储在叶节点导致查询时间复杂度固定为 log n
B-树查询时间复杂度不固定,与 key 在树中的位置有关,最好为O(1)
B+树叶节点两两相连可大大增加区间访问性,可使用在范围查询等
B-树每个节点 key 和 data 在一起,则无法区间查找
B+树更适合外部存储(存储磁盘数据)。由于内节点无 data 域,每个节点能索引的范围更大更精确。

**

4.Mysql索引是如何实现的

**
4.1 InnoDB 中的 B+Tree
InnoDB 是通过 B+Tree 结构对 ID 建索引,然后在叶子节点中存储记录。采用 InnoDB 引擎的数据存储文件有两个,一个定义文件,一个是数据文件。

若建索引的字段不是主键 ID,则对该字段建索引,然后在叶子节点中存储的是该记录的主键,然后通过主键索引找到对应的记录。

mysql索引底层结构B树和B+树_第3张图片

4.2 Myisam 中的 B+Tree
Myisam 引擎也是采用的 B+Tree 结构来作为索引结构。由于 Myisam 中的索引和数据分别存放在不同的文件,所以在索引树中的叶子节点中存的数据是该索引对应的数据记录的地址,由于数据与索引不在一起,所以 Myisam 是非聚簇索引。

mysql索引底层结构B树和B+树_第4张图片

你可能感兴趣的:(面试)