1,B+树
2,B树(B-树)、B*树,以及为什么选用B+树。
3,MySQL与B+树
4,B+树的作用总结
1,B+树
B+ 树是从平衡二叉查找树演化而来(但B+树不是二叉树,而是一个多叉查找平衡树)。
下图就是一颗平衡二叉查找树
借助网页工具:Data Structure Visualization (usfca.edu)
现在我们将其改造成 B+ 树
树的阶数表示一个节点最多能有多少个子节点。
每个叶子页(LeafPage)存储了实际的数据,如下图中有的叶子页就存放了3条数据记录,当然可以更多,叶子节点由小到大(有序)串联在一起,叶子页中的数据也是排好序的;
从AVL到B+树的变化可知,如果节点特别多的话,AVL树的高度远远高于B+树。
我们可以归纳出B+树的几个特征:
1、相同节点数量的情况下,B+树高度远低于平衡二叉树;
2、非叶子节点只保存索引信息和下一层节点的指针信息,不保存实际数据记录;
3、每个叶子页(LeafPage)存储了实际的数据,比如上图中每个叶子页就存放了3条数据记录,当然可以更多,叶子节点由小到大(有序)串联在一起,叶子页中的数据也是排好序的;
4、相邻的叶子节点之间用指针相连。
注意:叶子节点中的数据在物理存储上完全可以是无序的,仅仅是在逻辑上有序(通过指针串在一起)。
当然,一棵m阶的B+树完整定义如下:
-
每个节点最多可以有 m 个元素;
-
除了根节点外,每个节点最少有 (m/2) 个元素;
-
如果根节点不是叶节点,那么它最少有 2 个孩子节点;
-
所有的叶子节点都在同一层;
-
非叶子节点只存放关键字和指向下一个孩子节点的索引,记录只存放在叶子节点中;
-
一个有 k 个孩子节点的非叶子节点有(k-1) 个元素,按升序排列;
-
某个元素的左子树中的元素都比它小,右子树的元素都大于或等于它(二叉排序树的特征);
-
相邻的叶子节点之间用指针相连。
2,B树(也可以是B-树)、B*树,以及为什么选用B+树。
B树也B+树的差别是,B树的非叶子节点也需要存放数据,下图是B树
而B+树的话,数据只存在叶子节点上,同时相邻的叶子节点有链表的结构
同时要注意,MySQL中实现的B+树,叶子节点之间的链表是双向链表,这是一个细微的差别。
-
另外B* 树的话,与B+树的差别就是在非叶子节点之间,也有相互的指针指向。Oracle中使用的是B* 树。那为什么MySQL不用B树而使用B+树呢?
-
因为B数据每个节点都存储数据,每次查询的数据大小固定,就会造成每次查询返回的数据的条数变少,相同数据规模的情况下B树会增加io次数,而B+树,则数据量较小,一次可以返回多条记录,io次数较少
-
范围查询B+树明显优于B树
3,MySQL与B+树
为什么关系型数据库都选择了B+树,这个和磁盘的特性有着非常大的关系。
为了提高效率,要尽量减少磁盘I/O。为了达到这个目的,磁盘往往不是严格按需读取,而是每次都会预读,即使只需要一个字节,磁盘也会从这个位置开始,顺序向后读取一定长度的数据放入内存,这个称之为预读。
预读的长度一般为页(page)的整倍数。页是计算机管理存储器的逻辑块,硬件及操作系统往往将主存和磁盘存储区分割为连续的大小相等的块,每个存储块称为一页,页大小通常为4k。
按照磁盘的这种性质,如果是一个页存放一个B+树的节点,自然是可以存放很多的数据的,比如InnoDB里,默认定义的B+树的节点大小是16KB,这就是说,假如一个Key是8个字节,那么一个节点可以存放大约1000个Key,意味着B+树可以有1000个分叉。同时InnoDB每一次磁盘I/O,读取的都是 16KB的整数倍的数据。也就是说InnoDB在节点的读写上是可以充分利用磁盘顺序IO的高速读写特性。
同时按照B+树逻辑结构来说,在叶子节点一层,所有记录的主键按照从小到大的顺序排列,并且形成了一个双向链表。同一层的非叶子节点也互相串联,形成了一个双向链表。那么在实际读写的时候,很大的概率相邻的节点会放在相邻的页上,又可以充分利用磁盘顺序IO的高速读写特性。
所以我们对MySQL优化的一大方向就是 尽可能的多让数据顺序读写,少让数据随机读写 。
磁盘顺序读取的效率很高(不需要寻道时间,只需很少的旋转时间),一般来说,磁盘的顺序读的效率是随机读的40到400倍都有可能,顺序写是随机写的10到100倍。
4,B+树的作用总结
-
在磁盘设备上,通过B+树可以有效的存储数据;
-
所有记录都存储在叶子节点上,非叶子(non-leaf)存储索引(keys)信息;而且记录按照索引列的值由小到大排好了序。
-
B+树含有非常高的扇出(fanout),通常超过100,在查找一个记录时,可以有效的减少IO操作;
*扇出:是每个索引节点(Non-LeafPage)指向每个叶子节点(LeafPage)的指针;
*扇出数 = 索引节点(Non-LeafPage)可存储的最大关键字个数 + 1