数表的查找之 MySql 为什么使用 B+ 树?

数表的查找之 MySql 为什么使用 B+ 树?

讲解之前,先进行思考:

思考:从磁盘查找数据效率低,一般是什么原因?

我们知道 CPU 速度非常快,如果 CPU 直接与磁盘进行交互,由于磁盘的 IO 速度较慢,因此不能直接使CPU与磁盘交互,而是在之间引入内存,先将磁盘中的数据加载至内存,CPU 再从内存中读取数据。

数表的查找之 MySql 为什么使用 B+ 树?_第1张图片

解释到这里,继续回归先前的思考题,如果从磁盘查找数据消息低,那么一定是出现在磁盘的 IO 上。

影响 IO 效率的因素主要有两大类:

  • 读写数据越大,速度越慢;
  • 读写次数越多,速度越慢;

对于读写的数据大,这里没什么改变的办法,有时候的需求确实是读取大量的数据,但是对于读写的次数多,这里可以进一步优化——引入索引。


方式一:线性查找

对于线性查找,是最简单也是最原始的查找方式,它的缺点就是,查找效率非常低,对于每一次查找,都需要遍历全部数据,查询效率非常低。

数表的查找之 MySql 为什么使用 B+ 树?_第2张图片


方式二:哈希查找

既然线性查找效率非常低下,那么我们引入哈希表,通过元素值的 key 去查找对应的分支链表,这样查询效率有所提升,但是,哈希查找也存在弊端,因为哈希查找存在哈希冲突,一旦出现哈希冲突,极端的情况下就会出现一条单链表,时间复杂度还是O(N)。并且对于范围查找也非常不友好。

数表的查找之 MySql 为什么使用 B+ 树?_第3张图片

方式三:引入树查找—二叉树

对于二叉树,由于每个节点的值没有规律,查询起来还是需要一个个查找对比,还是很费劲,时间复杂度还是O(N),因此二叉树也不行。

数表的查找之 MySql 为什么使用 B+ 树?_第4张图片

方式四:二叉树改造之二叉排序树(BST)

既然二叉树的缺点是节点之间没有规律,那么换成二叉排序树怎么样?左子树永远比根节点小,右子树永远比根节点大。咋一看好像可以,但是仔细想想还是存在特殊情况:只有左子树或只有右子树。这样的时间复杂度依旧是O(N)。

数表的查找之 MySql 为什么使用 B+ 树?_第5张图片

方式五:二叉排序树(BST)改造之平衡二叉树(AVL)

既然二叉排序树会存在只有左子树或右子树的极端情况,那么我们引入平衡二叉树不就解决了?让树的形态永远保持平衡。但是啊,平衡二叉树的每一次调整平衡,都需要耗时,类似于是在用插入数据时的成本,来换取查询的效率。如果插入少查询多,那么这种方法也可取,但是插入多查询少时,就不可取了。

数表的查找之 MySql 为什么使用 B+ 树?_第6张图片

方式六:平衡二叉树(AVL)改造之红黑树

对于红黑树,在插入的时候虽然也需要进行红黑节点的调整,但是相对于平衡二叉树也有所好转。是不是红黑树就满足我们的需求了呢?假如我们插入了大量的数据,那么红黑树的深度也会特别深,树的深度越深,查找次数就会变多,因此效率也没有得到本质的改善。

数表的查找之 MySql 为什么使用 B+ 树?_第7张图片

方式七:红黑树改造之降低树的深度(B 树)

B 树解释:满足下列的 m 叉树就是一颗 B 树(B-Tree)不是 B- 树:

(1)树中每个结点至多有 m 个孩子结点(即最多只有 m-1 个关键字)。
(2)每个结点的结构为:

在这里插入图片描述
n 表示关键字及孩子个数,p表示指向孩子结点的指针,k表示关键字。

(3)除根节点外,其他结点至少有 m/2 个孩子结点。
(4)若根节点不是叶子节点,则根节点至少有两个孩子结点。
(5)所有叶子结点都在同一层上,即 B 树是所有结点的平衡因子都等于 0 的多路查找树。

数表的查找之 MySql 为什么使用 B+ 树?_第8张图片

既然二叉树无法避免树的深度变深,那么我们就想办法减少树的深度,因此引入多叉树如何?(引入B树,B树就是一个有序的多路查询树),树的叉数变多后,对于同一组数据,深度自然就会降低。

此处先引入一个名词:磁盘预读。

  • 内存跟磁盘发生数据交互的时候,一般情况下有一个最小的逻辑单元,称之为页:datapage。
  • 页一般由操作系统决定是多大,一般是 4k 或者 8k,在进行数据交互的时候,可以取页的整数倍来进行读取。

对于 B 树的每一个结点,都是放在一个 datapage 里面,每次查找数据时,都是先从磁盘中 IO 读取一个 datapage,然后依次往下查找,直到找到为止。假设一个结点的大小是16k,三层的B树就是16K * 16k * 16K = 4096K³,假如我们的数据超过4096K³,就只能继续往下加一层才能存储数据,这样向下加一层的做法,又变相的加深了树的深度,

你可能感兴趣的:(mysql,数据库)