Mysql实战-索引结构 B+Tree
上一篇 我们讲解了二叉树,平衡二叉树,红黑树,BTree的结构及特点,本文我们着重讲解一下B+Tree,为什么Mysql的存储结构采用B+Tree而不是上面的那几种
1.BTree的缺点
我们用上篇文章中的BTree的例子
想要访问定位60元素,要访问3次磁盘空间,由此可知,BTree查找效率与树的高度有密切的关系
- 当数据量大时,树的高度也很高
- 树的高度高,就导致读取磁盘IO很频繁,效率就很低下
- 当系统从磁盘读取数据到内存时是以磁盘块作为读取数据的基本单位
- 位于同一个磁盘块中的数据会被一次性读取出来,而不是需要什么取什么
- InnoDB存储引擎中有页(Page)的概念,页是其磁盘管理的最小单位
- 也就是说一次磁盘IO,就会读取一页的数据
- InnoDB在把磁盘数据读入到磁盘时会以页为基本单位,在查询数据时如果一个页中的每条数据都能有助于定位数据记录的位置
- InnoDB存储引擎中默认每个页的大小为16KB
- 参数innodb_page_size可以设置页Page的大小设置为4K、8K、16K
- 一个页的存储空间是有限的,如果data数据较大时将会导致一页能存储的key的数量大幅减小
- Key数量少,就会导致节点多,节点多 就会导致B-Tree的深度较大,高度高
- 高度高,查询时的磁盘I/O次数就多,查询效率就低
我们可以使用 命令,查看MySQL配置的页的大小:
mysql> show variables like 'innodb_page_size';
那么如何把瘦高的BTree 变为 矮胖的 树,方便查找呢?
2.B+Tree的原理
InnoDB存储引擎就是用B+Tree实现其索引结构,B+Tree是在BTree树上的一种优化,为的就是使BTree 更加的 矮胖(高度低, 且 叶子节点多), 使其更适合现在存储索引结构
在B+Tree中,所有数据记录节点都是按照键值大小顺序存放在同一层的叶子节点上,而非叶子节点上只存储key值信息,这样可以大大加大每个节点存储的key值数量,降低B+Tree的高度。
对比上面的BTree和B+Tree,我们可以很清晰的看到, 56/56/77 这三个元素下面是没有data数据的,中间元素不保存数据,只用来做索引,所有的数据全都保存在叶子节点,B+Tree有以下特点
- 非叶子节点只存储键值Key信息,因为没有data,一页可以存储很多Key
- 数据记录都存放在叶子节点中, 15/18/20/30 全都是叶子节点,叶子节点才有data数据
- 所有叶子节点之间都有一个链指针,底层15/18到20/30 节点中间有一个指针,按顺序指引
- 所有叶子节点形成有序链表,便于范围查询
原来的BTree 现在用B+Tree来展示,如图所示
3.B+Tree的树层级高度低,叶子节点多
B+Tree 的数据全部保存在末端的叶子节点中,这样有什么好处?
- 每页非叶子节点能够保存的索引Key值就会就很多,降低了树的高度了,树变矮了
- 这种存储导致末端的叶子节点的数量非常庞大,增大树的宽度, 树变胖了
- B+Tree保存2000多万条数据时,B+Tree 只要 3 层
- BTree 则需要至少 6 层 才能满足
BTree 的叶子节点之间没有双向指针,不能很好地支持范围查找
B+Tree 叶子节点之间有双向指针,从左到右的索引值是从小到大的顺序排序,可以高效支持范围的查找
4.为什么使B+Tree做索引,而不是红黑树
为什么用B/B+树这种结构来实现索引呢? 而不是用红黑树做索引呢 ?
我们先从红黑树的特点来解释
- 红黑树使存储在内存中才会使用的数据结构
- 在大规模存储数据的时候,红黑树不允许相邻父子红/红,黑/黑,这种难免会增加树的深度
- 树的深度过大,读取数据就会造成磁盘IO读写过于频繁
- 磁盘查找读取的次数往往由树的高度所决定,
- 高度高,读取次数多,IO读取效率低下,从而导致查询效率低下
所以,我们要把树变的 矮胖,设置树结构时尽量减少树的高度
5.B+Tree预读
为了提升效率,要尽量减少磁盘IO的次数。实际过程中,磁盘不是每次严格按照页的大小来读取,而是每次都会预读
磁盘读取完本次需要的数据后,根据局部性原理,一个数据被使用,它的相邻数据可能马上也会被使用,程序需要的数据可能比较集中, 这样磁盘读取会按顺序再多读一部分数据到内存中,避免频繁的磁盘IO读取
- 由于磁盘顺序读取的效率比寻道时间高,所以会预读,采用预读可以提高I/O效率
- 预读的长度一般为页(page)的整倍数。
- MySQL(默认使用InnoDB引擎),将数据记录按照页的方式进行管理
- 系统参数innodb_page_size可以设置每页Page的大小设置为4K
至此 我们讲解完了BTree和B+Tree的对比,并且分析了B+Tree为什么能够打败红黑树和BTree,成为Mysql御用的索引存储结构