MySQL专题(七):磁盘数据文件中的数据页的物理存储结构 MySQL索引的运作核心 基于主键的索引是如何设计的 一颗B+树的完整由来 更新数据的时候自动维护的聚簇索引到底是什么 ?聚簇索引的小总结

前言:

说明:本章开始更新实际索引相关的知识点
一:前置知识点《前因》

1.磁盘数据文件中的数据页的物理存储结构
2.假设没有任何索引,数据库是如何查询语句搜索数据的?
3.假设没有建立任何的索引,根据主键或者where其他字段条件查询数据的?
4.不断在表中插入数据时候,物理存储是如何进行页分裂的?
4.1.索引的运作核心,为啥主键要设计为自增呢?
4.2.非自增主键引发的页分裂

二:基于主键的索引是如何设计的,以及如何根据主键索引查询
三:索引的页存储物理结构,是如何用B+树来实现的?《后果》
四:更新数据的时候,自动维护的聚簇索引到底是什么?
五:聚簇索引的小总结

一:前置知识点《前因》

1.磁盘数据文件中的数据页的物理存储结构

大量的数据页在disk中是按顺序一页一页存放的,任何两个相邻的数据页之间会采取双向链表的格式互相引用,数据页内部会存储一行行的数据,也就是表里插入的一行行的数据都会存储在数据也中,然后数据页的每一行数据都会按照主键大小进行排序存储,同时每一行数据都有指针向下一行数据的位置,组成单向列表,大概看上去就是图中的这个模样:如图
在这里插入图片描述

2.假设没有任何索引,数据库是如何查询语句搜索数据的?

每个数据页都有一个页目录,里面根据数据行的主键放了一个目录,同时数据行是被分散储存到不同的槽位【一个数据行在disk上的位置】中的,所以实际上在每个数据页的目录中,这个页的每个主键跟所在的槽位都有映射关系。如果有主键的情况下查找举例:根据主键查找一条数据,假设此时数据库中的表没几条数据,表中总共就一个数据页,那么就太简单了,首先回到数据页的页目录根据主键进行二分查找,通过二分查找在目录中快速定位到主键对应的数据是在哪个槽位,遍历槽位的每一行数据,就能快速找到那个对应的数据了《每个槽位中都有一组数据,根据主键找到槽位,遍历查找即可》,反之没有主键,那么就需要进入数据页中,根据单向链表一次遍历查找数据了,性能就极差了。也就是变成了图中的这样:
在这里插入图片描述

3.假设没有建立任何的索引,根据主键或者where其他字段条件查询数据的?

从第一个数据页开始遍历所有的数据页,先从disk加载到buffer pool的缓存页中。如果根据主键:在数据页的页目录中根据二分查找进行查找,如果是根据where条件后的字段,根据数据页内部的单向链表来遍历查找,可能会出现的问题:加载的某个数据页没找到想要/匹配的数据《继续加载下一个数据页,以此类推》幸运还好,不幸运可能就是全表扫描。

4.不断在表中插入数据时候,物理存储是如何进行页分裂的?

正常插入一些数据后,都会进去到一个数据页中去,在数据页的内部,会组成一个单向链表《其中就是一行行的数据,刚开始的第一行是起始行,行类型是2,指针指向下一行数据,每一行数据都有自己每个字段的值,每一行通过一个指针不停的指向下一行数据,普通的数据行类型都是0.最后一行类型为3的,就是代表最大的一行数据》随着表里的数据越来越多,就会继续新增一个16KB的数据页,这两个数据页关联就是双向链表。

4.1:索引运作的核心

索引运作的核心基础就是要求后一个数据页的主键值都要大于前面一个数据页的主键值《如果主键是自增的,可以保证这一点,因为新插入后一个数据页的主键值一定大约前一个数据页的主键值》

4.2:非自增主键引发的页分裂,也就是数据页的数据进行的相互移动

那么如果不是自增的主键,例如第一页的第一条数据的主键是10,第二页的第一条数据是8.此时就会出现页分裂,实际上会将前一个主键值较大的数据行移动到新的数据页中,将主键值比较小的数据行移动到新的数据页中,保证新的数据页中的主键值一定比旧的数据页中的主键值大,页分裂图示:
MySQL数据页分裂

二:基于主键的索引是如何设计的,以及如何根据主键索引查询

2.1:为了避免全表扫描尴尬的事情发生:此时就需要为主键设计一个索引了,针对主键的索引设计上就是主键目录。例如现在要找id=3的数据,此时就在主键目录中跟每个数据页的最小主键比对,id = 3大于数据页2中的最小主键值,小于数据页8中的最小主键4,那么就可以定位到id=3的数据一定是在数据页2中【这样效率直线上升】也就变成了这样如图:
在这里插入图片描述

三:索引的页存储物理结构,是如何用B+树来实现的?《后果》

3.1:问题:表里的数据有千万级,亿级,单表几个亿的数据量,此时用主键目录是否还能行的通呢?

实际上最后采用的是把索引数据存储在数据页中的。《也就是说,表里的实际数据是放在数据页中的,表的索引实际上也是放在数据页中的》此时索引放在数据页之后,就会有索引页,假设有很多很多的数据页,那么此时就可以有很多的索引页,有很多索引页。

3.2:如何知道应该到哪个索引页去查找?

继续演变:将索引页多加一个层级出来,在更高的索引层级中,保存了每个索引页和索引页中最小主键值,此时需要找id=46的数据行,会直接先到最顶层的索引页35号索引页去找,直接通过二分查找定位到下一步的索引页20去找,接下来通过索引页20通过二分查找定位,也很快定位到数据在数据页8中,在进入到数据页8中,就可以找到id = 46的数据行了。

3.3:问题继续横向扩展:假设最顶层的索引页中存放的下层索引页的页号也太多了,怎么办?

再加一层索引层呗,实际上通过一系列的算法,算出来三层的索引页,大约可用存储千万级别的数据量。【这里有一个楼梯原理,简单过一遍,楼层越高,IO次数越多,反之】最终版的B+数的概念就引出了。
整体演变过程图解:
B+树的完整演变过程

四:更新数据的时候,自动维护的聚簇索引到底是什么?

4.1:聚簇索引到底是什么?

所有的索引页+数据页组成的B+树就是聚簇索引。原理:一颗大的B+树索引数据结构中,叶子节点就是数据页自己本身,那么此时就可以称这颗B+树的索引为聚簇索引。

4.2:聚簇索引检索案例

假设要搜素一个主键id对应的行,此时就应该先去顶层的索引页88中去查找,通过二分查找发定位到某个索引页去查找,例如现在定位到了下层的索引页35中去找,此时索引页35中也有一些索引条目的,分别都是下层各个索引页(20,28)和数据页对应最小的主键值,此时在索引页35的索引条目里继续二分查找,很容易就定位到,应该在到下一层的哪个索引页去查找,跟着索引页35接着就找到下层的索引页28中去了,此时28的索引页中肯定也是有索引条目的,这里就存放了部分数据页页号(例如数据页2,数据页8)和每个数据页中最小的主键值,此时继续发生二分查找发去定位某个数据页,例如定位到数据页2,里面就有一个页目录,都存放了各行数据的主键值和数据行的实际物理位置(槽位),此时直接二分查找,就可以快速定位到要搜索的主键值对应的行的物理位置,然后直接在数据页2中找到数据即可。《基于索引数据结构去查找主键的一个过程》如B+查找结构图:
B+树结构图

五:聚簇索引的小总结

在最下层的索引页都是会有指针引用数据页的,所以实际上索引页之间跟数据页之间是由指针链接起来的。《对于同一个层级内的索引页,互相之间都是基于指针组成双向链表的》,也就是同一层级内的索引页组成双向链表和数据页自己组成的双向链表是一样的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咖喱ABC

无需打赏,共同进步学习!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值