赞
踩
之前的文章说过,InnoDB存储数据的单位是页,各个数据页之间采用双向链表
连接起来;而每个数据页中的记录之间又通过单向链表
连接,而记录又分为若干个组
,组采用最大记录
的记录信息作为槽
信息,多个槽组合成页目录
;当用户查询某条记录 A 时,先使用二分法在页目录
中找到主键值比 A 的主键值大且差值最小的槽
,然后再使用二分法找到对应的记录。
在一个页中查找一条记录,当知道主键时可以采用前言
中的方法快速查找到对应的记录;
但是如果是其他列信息为查询条件就没这么幸运了,因为页中的记录都是根据主键排序的,无法通过二分法查找到记录,只能一条条遍历。
在没有索引的情况下只能通过双向链表
遍历页中数据才能够找到对应的记录。
注意:是通过双向链表
遍历页,进入到页中使用二分法查找页目录来确定此页中是否存储在对应记录,并不是遍历所有记录。
在真实业务中,数据记录往往是非常多的,一页无法将记录存储完毕,需要很多页来存储。而通过双向链表
遍历的方法查找记录是相当低效的,严重的还可能导致数据库崩溃。所以开发数据库的叔叔们给出了索引
的概念。
当用户插入用户记录的时候,会进行一系列的判断。首先判断本页的记录存储空间是否已满,如果满了就会进行重新排布,同时生成一个新的页空间,将主键靠后的记录分派到新页中,我们称这个过程为页分裂
。学习过数据结构中 B+ 树的同学可能会感觉到熟悉。
页分裂具体流程如下图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JuxDbge8-1643190422249)(https://kuangstudy.oss-cn-beijing.aliyuncs.com/bbs/2022/01/26/kuangstudy1bb8b927-da46-4120-be3e-c9dddd04f2ad.png “页分裂后”)]
当记录数越来越多,数据页也越来越多的时候,数据库的运行效率就会变得极低,为了提高查询的效率。InnoDB采用了和存储记录时一样的方法,给数据页创造一个目录,使用这些目录记录就能通过二分法快速定位到记录在那个数据页中。
那么什么是索引的呢?
索引说白了就是数据页的目录
,其本质上也是记录,只不过其存储的是页号 + 列
的信息,页号
就是存储真实数据的页,列
主要是为了做出区分。
为了区分页目录
,下面将数据页的目录称之为目录项记录
,而将存储真实数据的记录称之为用户记录
。
目录项记录主要包含两个方面的字段:
具体如下图:
既然都是记录,那么这么进行区分呢?其实可以通过记录头信息中的record_type
属性来区分,具体的属性为:
学习过数据库的都知道索引的底层逻辑是 B+ 树,但是目前出现的并不是一颗树,这是怎么回事呢?
其实是索引并没有完善,还是会有隐患。当页数越来越多,尽管通过目录项记录
可以快速定位到数据页,但是当目录项记录
逐渐增多,遍历查找目录项记录
的效率降低了,整体效率也高不上去,所以开发数据库的叔叔们将这些记录使用页来存储,通过处理用户记录
的方式来处理目录项记录
。
将目录项记录
用数据页存储,当目录项记录的数据页足够多的时候,可以为这些数据页再创建目录项记录
,如此反复,这样的操作最后都会结束,然后终止于根节点。
索引根据排序的列不同分为三种索引:聚簇索引、二级索引、联合索引
聚簇索引是InnoDB的默认索引,也是InnoDB引擎的数据库在存储数据时使用的索引。是的,索引并不是程序员创建才有,当插入数据时,InnoDB引擎数据库就将数据按照聚簇索引的方式进行了排列,以方便后续查询。
那么聚簇索引是什么呢?
聚簇索引就是根据主键+页号
为关键字排序的索引,聚簇索引有两个特点:
聚簇索引是根据主键排序的,也就是说聚簇索引只能加快以主键为查询条件的查询语句,那么我要以非主键为查询条件时应该怎么办?可以使用二级索引。
二级索引根据指定列 + 索引
进行排列,其有三个特点:
主键+指定列
指定列+页号
由于二级索引的用户记录存储的不是完整信息,所以使用二级索引往往只是一个过渡,使用二级索引查询到对应的主键后,再使用主键进行聚簇索引查询,查询完整内容,这也是二级索引名称的由来,这个过程也称之为回表
。
查找过程:
目录项记录
页目录及录项
,然后进入到对应用户记录
页中查询数据之前两个说的都是单列查询索引,联合索引就是使用多列值进行排序的索引。
其和二级索引都差不多,只是在排列上不同而已,联合索引先根据指定列1
进行排序,然后再对重复记录根据指定列2
进行排序。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。