Mysql技术内幕:聚集索引,非聚集索引的底层实现——详解
一.B(B-)树与B+树的简介
- 在了解Mysql数据库索引的实现之前,就必须知道B树与B+树的相关知识,否则根本无法进行学习
1.1 B(B-)树
- 首先明确一个概念:B树就是B-树
- 如果想要详细学习B树或者B-树,那么就看这篇博客:B树详解
- 这里仅仅对B树做一个简单的介绍
1)B树是平衡树,类似于二叉排序树,所以左子节点的数据一定小于父节点,右子节点的数据一定大于父节点
2)但是B树每一个节点的结构是一个线性表,分别存储关键字(key:也就是数据)和指向子节点的指针。
3)举个例子:例如如图的【3,7】节点,实际上里面存储的是
【point1, 3,point2, 7,point3】
4)所以每次查询的时候从根节点开始比较关键字,如果找不到就去子节点找
5)至于B树的插入删除这里就不介绍了,自己看上面的博客连接
1.2 B+树简介
- B+树是B树的变式,两个各有千秋
- 如果想要学习B+树的详细知识可以看这篇博客:B+树详解
- B+树最大的区别就是所有的数据都是存储在叶子节点上的,而非叶子节点中存储的都是数据索引。并且所以的叶子结点再连城一个链表!
- B+ 树的三个优点:
1)层级更低,IO 次数更少,因为非叶子节点中不存储数据,只存储索引,这就导致里面可以存储更多的索引!所以IO的次数更少,整个树变变的矮胖起来
2)每次都需要查询到叶子节点,查询性能稳定,而B树的查询性能是不稳定的,有时候可能在根节点查到,有时候可能在叶子结点查到
3)叶子节点形成有序链表,当我们进行即品范围查询的时候,直接在这个链表中寻找范围即可,范围查找更加方便
二. 聚集索引
2.1 聚集索引的概念
- 我们在进行数据库建表的时候,经常会给表加上主键,没有主键的表其实在磁盘上是无序的整齐存放的,和我们所认知的‘表’的结构很相似
- 当给表加上主键的时候,这个表就会转化成我们刚刚所说的B+树的形状,相当于整个表就变成了一个索引,所以这就成为聚集索引
- 也就是为什么一个表只能由一个聚集索引
2.2 聚集索引的查找
- 每次查找的时候,都是根据主键进行查找的,也就是非叶子结点中存储的就是主键中的数据,每次查找都要找到相应的叶子结点,然后取到相应的数据
2.3 比较聚集索引查询效率
- 当我们不使用聚集索引的时候,查询的时候是一行行的查找,每次都需要进行磁盘IO,时间复杂度是O(n)
- 当我们使用聚集索引的时候,时间直接变成了O(logn)
2.4 聚集索引带来的问题
- 有了聚集索引,那么查询自然是快了许多,但是实际上为增,删等写入数据的操作变慢
- 原因是因为每次写入操作都需要进行平衡二叉树的判断,修改树的结构,这样肯定是浪费了时间的!
三. 非聚集索引
3.1 非聚集索引的概念
- 非聚集索引就是讲主键以外的字段作为索引,其实就是我们平常所使用的索引
- 每次当我们定义一个字段为非聚集索引,那么数据库就会将这个表中的该字段复制一份构成一颗B+树,这棵B+树中的叶子结点存储的是相应的主键,非叶子结点存储当然是索引指针了
- 如果我们定义多个字段分别为非聚集索引,那么就会生成多颗B+树,并且是不互相干扰的!
3.2 非聚集索引的查找
- 非聚集索引的查找其实就是最终查找到相应的主键,然后再通过聚集索引树去查找数据——所以可以看做是二次查找
- 也就是说无论以任何方式查找表,最终都要用主键通过聚集索引来定位数据——除了覆盖索引(下面会讲到)
三.覆盖索引
3.1 覆盖索引的概念
- 覆盖索引指的是将多个字段一起设置为索引,也就是组合索引
- 和非聚集索引一样,同样会生成一科非聚集索引树,
3.1 覆盖索引的查找过程
- 例如将username和userbirthday作为组合索引
- 我们的查找目标是:userbirthday。
- 查找的时候首先在非聚集索引树中查找该索引,找到相应的数据主键
- 但是这时候我们就要注意了,一般情况下我们又要回到聚集索引树中去根据主键查找该用户的userbirthday,但是实际上我们的非聚集索引树中已经存储了该数据,所以可以不用做这一步了!直接取到数据
四.总结
- 这就是聚集索引,非聚集索引,覆盖索引的概念和实现了,我觉得讲的还是比较清楚的
- 该篇博客的编写参照了这篇博主的文章:https://blog.****.net/itguangit/article/details/82145322
- 希望能对大家有帮助,有帮助的话可以点个赞喔!谢谢!