本篇博客学习于csdn直播课https://live.csdn.net/room/weixin_48013460/
初步学习总结,深入学习可以看看视频内容,看不到视频的话,评论区有百度网盘视频连接。

什么是索引,为什么要用索引

数据库索引是一种为了加速数据表中行记录检索的数据结构。
注意:数据库中的索引存储于磁盘中。

这里我们给出一个例子select * from t_user where id = 102;
索引机制深入浅出
这里我们不使用索引的时候,我们会在这个表中依次查找id=102的这条数据,如果说我们这个数据库存储的是千万乃至上亿的数据量时,可以想到这个工作方式多么浪费性能。

所以这时候索引的优势就出来,索引是一种数据结构,这里就相当于我们把id这一列数据单独拿出来保存在数据结构当中,当我们寻找id=102时可以快速返回这个数据在磁盘指针地址。

索引的数据结构

前面说到了索引是通过数据结构来帮助我们进行快速查找,索引使用的数据结构是什么呢?
其实就是数据结构中常见的树。

首先来理解一下:
1. 二叉树:
索引机制深入浅出
二叉树的特点:

  • 左小右大(通过关键字一分为二)
    简单来说就是某节点的值大于左子树小于右子树。
  • 递归的二分法查找,查找效率Olog(N)
    比如我们查找29这个数,首先44 => 25(29<44) ==> 32 ==>29

从上面的例子已经可以看出当我们使用二叉树时已经可以轻松的过滤掉很多的数据。但是二叉树其实也存在很多问题。如下图:
索引机制深入浅出
很明显这也是一个二叉树,只不过它在插入的过程中,插入的是一条递增序列。这在我们数据库中很常见,因为很多时候我们在设置数据库表的id主键是通常使用自增序列。这样这颗二叉树就变成了一个链表结构。问题也很明显的暴露出来了,当我们要查询5这个数据时我们就需要遍历整个链表才行。

所以说二叉树虽然能带给我们一定的优化但是在某些情况下它也存在着许多问题,那么还有其他的解决办法吗?

2. 平衡二叉树(AVL树)
索引机制深入浅出
平衡二叉树的特点就是某节点的两个字节的高度差绝对不能超过1(也就是说两个字节的深度差不能超过1) 也就是说这里就避免了前面二叉树会存在形成单链表的情况。

看一组avl树的插入过程你就能明白他是如何实现的:
索引机制深入浅出

在这个树中我们要插入一个0005时,会变成如下情况
索引机制深入浅出
这就是这个树型结构为了满足他的字节的高度差不超过一的特点,在遇到刚刚的插入情况时会进行一个向左的旋转来维护它的相对平衡。(在越来越多的数据插入过程中它都会通过左旋或右旋来维持它的相对平衡

即便是这样AVL树依旧存在着一些问题:

  • 树高问题:虽然AVL树在我们的搜索过程中能过滤掉很多数据,但是在实际开发中几百万条数据是很常见的,这种情况下AVL树的树高还是很高的。(树高带来的直接问题就是io的次数过多)(索引是存在硬盘当中)
  • io的利用率低:操作系统和磁盘交互是采用一种固定的单位来进行交换的(页),操作系统一页就是4KB,相当于一次交互需要4k的数据拉取,但是一个关键字只有几个几节的大小,是完全无法填充4kb的数据空间。(浪费太多)

3. 多路平衡查找树(B-树)
索引机制深入浅出此时我们要查找29时,在磁盘块1中 (17<29<35)前往磁盘块3,(26<29=29)在磁盘块9中找到位置。

B-树的特点:

  • 所有子节点都在一个水平线上。
  • 一个磁盘块一个节点存放的关键字不止一个。
    比如下面这个磁盘块:
    索引机制深入浅出它分为5块:
  • 1<x<17 走子节点(最左边的子树)
  • x=17 走自己
  • 17< x<35 走子节点(中间的子树)
  • x=35 走自己
  • x>35 走子节点(最右边的子树)

所以我们可以看出 分支子树的个数 = 关键字个数 + 1

这里我们把每一页中放满关键字可以提高磁盘利用率,并且关键字的存放量能达到几千上万个,所以它树高会很低,在关系型数据库中它的树高不超过四层,一般三层都能解决。

注意:
b树结构虽然对看起来在查找索引的过程非常好,但是实际上在生成这颗树的过程中会通过不断通过节点的分裂或合并来位置绝对的平衡。这里就会产生一个问题:有时候当我们数据量很大的时候,当我们突然插入某些数时很有可能让我们的树结构发生巨大的变化,这中间的带来的性能损耗可能高于查找的损耗。

所以说在一些经常发生变动的字段上不宜建索引,一般情况都是推荐使用自增的id来建立索引,它带来树结构的变化就比较小。

这里补充一个知识点
不了解hashmap可以看看我以前的一篇博客(https://blog.csdn.net/dekulugu/article/details/108658198)

hash索引和b树索引的区别:
了解过hashmap就知道,hashmap的数据结构是数组加链表,因为数组的位置是通过hash函数计算出来的,带有无序性所以不支持范围查找,但是b树索引是支持范围查找的。

4. B+树
索引机制深入浅出b+树特点:

  • 在根节点和支节点中不再存在数据区。
  • 所有的叶子节点上才会有对应的数据区内容
  • 数据的比较过程采用左闭合的比较方式
  • 在叶子节点上存在双向的链式结构

b+树的比较规则稍有变化,
上图为例:1<=x<28 走p1 , 28<=x<66 走p2,66<x 走p3.

  • 而且根节点和支节点没有数据区,也就是说我们在根节点明中1的时候还得继续走到叶子节点才能拿到数据。这样其实提高了稳定性,因为我们在b树结构中如果拿到叶子节点数据的时候,那么前面根节点和分支节点读取出的数据都是没有用的。而在我们b+树结构中可以说每一次io都是我们想要的内容,所以io利用率更高。

  • 基于b树我们需要全表扫描,b+树则只需要扫描叶子节点
    所以b+树的表扫描性性能高于b树

  • b+树天然形成了一个链表,对于排序能力更强

相关文章: