mysql索引为啥要选择B+树 (下)

有读者在 mysql索引为啥要选择B+树 (上) 上篇文章中留言总结了选择 B+ 树的缘由,大致上说对了,今天咱们再一块儿来看看具体的缘由。mysql

  • 索引为何要保存在硬盘中

首先要明白几个概念,服务器存储通常份内存和硬盘,内存的大小相对于硬盘来讲是很小的。内存的访问速度是纳秒级别的,很是快,而硬盘的访问速度相对内存来讲就比较慢了。算法

不论是访问内存仍是硬盘数据,操做系统都是按数据页来读取数据的,即每访问一次硬盘或内存,只读取一页大小的数据,一页的大小约等于 4 kb,向硬盘读取数据的操做叫作磁盘 IO。sql

看到这里你或许会知道了 mysql 索引为啥不保存在内存中了吧,一方面是虽然内存访问速度快但容量通常都比较小,存不了多少数据,再一个 mysql 须要让数据持久化,若是服务器断电或异常重启会致使数据丢失。数据库

  • 怎么让二叉搜索树支持区间查询

上篇文章中提到过二叉搜索树,为了让二叉搜索树也支持区间查询,咱们把二叉树的叶子节点经过一个双向链表来链接,而且这个链表是有序的,注意叶子节点和普通节点是不同的,注意看下面的图。服务器

所以只须要先找到区间的起始值在链表中的位置,而后再日后遍历,直到遍历到区间的终止值,便可完成区间查询。以下图查找 7-30 这个区间的数据。数据结构

  • 如何提高查询速度

由于二叉搜索树保存在硬盘中,咱们每访问一个节点,就对应着一次硬盘 IO 操做,上面有说过向硬盘读取数据速度比较慢。所以树的高度就表明硬盘 IO 操做的次数,因此咱们要想办法让树的高度变矮,来减小硬盘 IO。性能

要想树变矮一些,那就把树多分一些叉来吧,变成一颗多叉树。下面分别用二叉树和五叉树来存储 16 条数据,看下树的高度又怎样的变化。mysql索引

根节点通常存储在内存中,普通节点和叶子结点保存在硬盘中,所以显然二叉树的高度为 5,须要 5 次硬盘 IO,而五叉树的高度为 2,查询一个数据只须要 2 次硬盘 IO。操作系统

固然这仅仅是一个小数据的例子,若是有一亿条数据,咱们构建一个 100 叉树,这棵树的高度也只有 3,所以多叉树能大大下降硬盘 IO,提高查询速度。指针

那么问题又来了,对于相同的数据量,是否是构建的多叉树的叉越多越好呢,由于叉越多树的高度就会越矮。

上面有说过操做系是按数据页大小来访问硬盘的,每次 IO 只读取一个数据页大小的数据,若是要读取的数据大于一个数据页,则会致使屡次 IO。所以咱们要尽可能让每一个节点的数据大小恰好等于一个数据页大小,即每访问一个节点只需一次 IO。

  • 插入和删除数据怎么办

上面讲的其实都是为了提升查询性能的,mysql 一般还有插入和删除操做的,这里咱们再简单说一下 B+ 树如何处理插入和删除节点的操做。

这里咱们把多叉树称做 m 叉树,这个 m 值是经过数据页大小和节点数计算出来的,尽可能保证每访问一个节点就是一个数据页的大小,并且每一个节点最多只有 m 个子节点。

如今咱们要往数据库中插入新的数据,即要往 m 叉树中插入新的节点,这可能就会致使某些节点的子节点个数大于 m,也就会致使该节点大小大于一个数据页,访问该节点就须要屡次 IO。

为了解决这个问题,m 叉树会把该节点分裂成两个节点,而后改分裂操做又会致使其父节点的子节点数可能超过 m,咱们再用一样的方法分裂节点,一直影响到根节点。

删除操做也是相似的思想,若是有频繁的删除节点,就会致使某些节点的子节点过少,就会浪费存储空间并下降查询效率。因此就要想办法让这些节点合并起来,合并的话就有可能会致使其子节点数超过 m,超过的话就再用上面的分裂方法分裂子节点。

关于节点分裂和合并操做就简单说这些了,也不画图了,知道这个处理思想就行了。

下面再总结一下 B+ 树:

B+ 树就是一种多叉树,是由二叉搜索树不断演变过来的,为了知足区间快速查询,B+ 树的叶子节点经过双向链表串联起来。

这里使用双向链表是为了支持顺序和倒序查询,虽然双向链表相对于单向链表虽然会浪费一倍的指针空间,可是在硬盘中这点空间几乎微乎其微,用这点空间换时间是一件很值得的事情。

B+ 树的子节点数不超过 m 个,同时也不能少于 m/2 个,一旦超过就须要分裂,一旦少于就须要合并。

关于 mysql InnoDB 引擎为啥要选择 B+ 树就写到这了,文中图片来源于极客时间《数据结构与算法之美》专栏。对文章若有疑问,欢迎留言交流,如文章有描述不当之处,也但愿你们批评指出。如文章对你有帮助,点个赞再走哈,感谢支持。

相关文章
相关标签/搜索