MySQL为什么要用B+树实现索引

  • Post author:
  • Post category:mysql


我们都知道MySQL的索引主要以B+树为主,但是要问到为什么用B+树呢?本文就来从头到尾介绍下数据库的索引。


索引是一种数据结构,用于帮助我们在大量数据中快速定位到我们想要查找的数据。

索引在mysql数据库中分三类:

B+树索引、Hash索引、全文索引。

今天介绍的是innodb存储引擎中的的B+树索引。

要介绍B+树索引,就不得不提

二叉查找树,平衡二叉树和B树

这三种数据结构。B+树就是从他们仨演化来的。



二叉查找树

在这里插入图片描述
从图中可以看到,我们为user表(用户信息表)建立了一个二叉查找树的索引。图中的圆为二叉查找树的节点,节点中存储了键(key)和数据(data)。

# 我们通常使用以下语句来创建索引
CREATE INDEX index_name ON table_name (column_name)


二叉查找树的特点

就是:


任何节点的左子节点的键值都小于当前节点的键值,

右子节点的键值都大于当前节点的键值。


顶端的节点我们称为根节点,

没有子节点的节点我们称之为叶节点。

如果我们需要查找id=12的用户信息,利用我们创建的

二叉查找树索引,查找流程如下

  1. 将根节点作为当前节点,把12与当前节点的键值10比较,12大于10,接下来我们把当前节点>的右子节点作为当前节点。
  2. 继续把12和当前节点的键值13比较,发现12小于13,把当前节点的左子节点作为当前节点。
  3. 把12和当前节点的键值12对比,12等于12,满足条件,我们从当前节点中取出data,即id=12,name=xm。

    利用二叉查找树我们只需要3次即可找到匹配的数据。如果在表中一条条的查找的话,我们需要6次才能找到。

如果上面的二叉树是这样的构造:

在这里插入图片描述

二叉查找树变成了一个链表。

如果我们需要查找id=17的用户信息,我们需要查找7次,也就相当于全表扫描了。

导致这个现象的原因其实是

二叉查找树变得不平衡了,也就是高度太高了,从而导致查找效率的不稳定。


为了解决这个问题,我们需要保证二叉查找树一直保持平衡,就需要用到

平衡二叉树

了。



平衡二叉树

平衡二叉树又称AVL树,在满足二叉查找树特性的基础上,要求

每个节点的左右子树的高度差不能超过1

下面是平衡二叉树和非平衡二叉树的对比:

在这里插入图片描述
平衡二叉树相比于二叉查找树来说,查找效率更稳定,总体的查找速度也更快。

我们都知道

平衡二叉树可是每个节点只存储一个键值和数据的

。每查找一次数据就需要从磁盘中读取一个节点,也就是我们说的一个磁盘块。如果我们要存储海量的数据呢?可以想象到二叉树的

节点将会非常多,高度也会及其高

,我们查找数据时也会进行

很多次磁盘IO,我们查找数据的效率将会极低

!这时候,就需要用到B树了。



B树

即为平衡树的意思,下图即是一颗B树。

在这里插入图片描述
B树相对于平衡二叉树,

每个节点存储了更多的键值(key)和数据(data)

,并且

每个节点拥有更多的子节点

,子节点的个数一般称为阶,上述图中的B树为3阶B树,高度也会很低。

假如我们要查找id=28的用户信息,那么我们在上图

B树中查找的流程如下

  1. 先找到根节点也就是页1,判断28在键值17和35之间,我们那么我们根据页1中的指针p2找到页3。
  2. 将28和页3中的键值相比较,28在26和30之间,我们根据页3中的指针p2找到页8。
  3. 将28和页8中的键值相比较,发现有匹配的键值28,键值28对应的用户信息为(28,bv)。

B树节点中

不仅存储键值,也会存储数据

。之所以这么做是因为在数据库中页的大小是固定的,

innodb中页的默认大小是16KB



如果不存储数据

,那么就会

存储更多的键值

,相应的树的阶数(节点的子节点树)就会更大,树就会更矮更胖,

如此一来我们查找数据进行磁盘的IO次数就会再次减少,数据查询的效率也会更快



B+树

B+树是对B树的进一步优化。

B+树索引的

所有数据均存储在叶子节点

,而且数据是按照

顺序排列

的。那么B+树使得范围查找,排序查找,分组查找以及去重查找变得异常简单。而B树因为数据分散在各个节点,要实现这一点是很不容易的。

以innodb作为存储引擎的表,

表中的数据都会有一个主键

,即使你不创建主键,系统也会帮你创建一个隐式的主键。这是因为innodb是把数据存放在B+树中的,而B+树就是以主键为键值构建的索引。

在这里插入图片描述
有心的读者可能还发现上图B+树中各个页之间是通过双向链表连接的,叶子节点中的数据是通过单向链表连接的。

我们一定要记住这句话:

数据即索引,索引即数据



版权声明:本文为weixin_40025107原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。