Mysql数据库索引
Mysql数据库索引是基于什么数据结构的?
Mysql索引主要是基于Hash表 或者 B+树。
Mysql数据库索引常见问题
- 数据库索引为什么要使用树结构存储呢?
树的查询效率高,而且可以保持有序。 - 为什么数据库索引没有使用二叉查找树实现呢?
其实从算法逻辑上来讲,二叉查找树的查找速度和比较次数都是最小的。但是,我们不得不考虑一个现实问题:磁盘IO。数据库索引是存储在磁盘上的,当数据量比较大的时候,索引的大小可能有几个G甚至更多。当我们利用索引查询的时候,把整个索引全部加载到内存中显然不可能的。(解决方法:逐一加载每一个磁盘页,这里的磁盘页对应着索引树的节点。)
二叉查找树作为索引
假设树的高度是4,查找的值是10,那么流程如下:
- 二叉查找树的结构:
- 第1次磁盘IO:
- 第2次磁盘IO:
- 第3次磁盘IO:
- 第4次磁盘IO:
总结:磁盘IO次数等于索引树的高度。
B树(B-树)
B-树就是B树,中间的横线并不是减号。
B树是一种多路平衡查找树,它的每一个节点最多包含k个孩子,k被称为B树的阶。k的大小取决于磁盘页的大小。
B-树的优势:自平衡
下面来具体介绍一下B-树(Balance Tree),一个m阶的B树具有如下几个特征:
- 根结点至少有两个子女。
- 每个中间节点都包含k-1个元素和k个孩子,其中 m/2 <= k <= m
- 每一个叶子节点都包含k-1个元素,其中 m/2 <= k <= m
- 所有的叶子结点都位于同一层。
- 每个节点中的元素从小到大排列,节点当中k-1个元素正好是k个孩子包含的元素的值域分划。
我们以一个3阶B-树为例,来看看B-树的具体结构。树中的具体元素和上边的二叉查找树是一样的。
下面演示一下B-树查询的过程,假如我们要查询的数值是5:
- 第1次磁盘IO:
. - 在内存中定位(和9比较):.
- 第2次磁盘IO:
- 在内存中定位(和2,6比较):
- 第3次磁盘IO:
- 在内存中定位(和3,5比较):
通过整个流程我们可以看出,B-树在查询中的比较次数其实不比二叉查找树少,尤其当单一节点中的元素数量很多时。可是相比磁盘IO的速度,内存中的比较耗时几乎可以忽略。所以只要树的高度足够低,IO次数足够少,就可以提升查找性能。相比之下节点内部元素多一些也没有关系,仅仅是多了几次内存交互,只要不超过磁盘页的大小即可。这就是B-树的优势之一。
B-树的插入和删除
插入元素4
- 自顶向下查找4的节点位置,发现4应当插入到节点元素3,5之间。
- 节点3,5已经是两元素节点,无法再增加。父亲节点 2, 6 也是两元素节点,也无法再增加。根节点9是单元素节点,可以升级为两元素节点。于是拆分节点3,5与节点2,6,让根节点9升级为两元素节点4,9。节点6独立为根节点的第二个孩子。
删除元素11
- 自顶向下查找元素11的节点位置。
- 删除11后,节点12只有一个孩子,不符合B树规范。因此找出12,13,15三个节点的中位数13,取代节点12,而节点12自身下移成为第一个孩子。(这个过程称为左旋)
B-树的应用
B-树主要应用于文件系统以及部分数据库索引,比如著名的非关系型数据库MongoDB。