首页 > 数据库 >MySQL InnoDB索引原理

MySQL InnoDB索引原理

时间:2022-08-27 19:01:16浏览次数:106  
标签:记录 链表 索引 查找 分组 MySQL InnoDB 页面

 数据库与I/O原理

数据会持久化到磁盘,查询数据是就会有I/O操作,相对于缓存操作,I/O操作的时间成本相当高昂。

I/O操作的基本单位是一个磁盘页面,比如16KB的页面大小。当数据量比较大时,单表数据就会分布在多个磁盘页面。

如果没有索引,就必须按顺序加载磁盘页面到缓存进行查找,判断数据是否存在。随着数据量的增长,磁盘I/O操作的次数也会越来越多。

因此,有必要通过一些辅助的数据结构来提交检索的速度。

从上面可以看出,想要快速读取到数据,可从以下几个方面着手

1. 如何尽量减少磁盘IO操作

2. 如何快速定位到数据所在的磁盘页面

3. 如何快速定位数据在磁盘页面内的位置

 

数据库索引是什么

索引是存储引擎用于快速查找记录的一种数据结构。

举个类似的例子,当我们要阅读《高性能MySQL》的第五章时,一般会先查找目录,找到第五章对应的页码,然后翻到对应页码即可。

目录一般不会超过10页,整本书有将近700页。

如果没有目录,那么我们只能顺序或者使用二分的方法来查找第五章,需要翻页的次数就会更多。

索引的作用与书籍的目录相似,用于辅助快速查找目标数据。

 

存储结构

记录(行)格式

InnoDB支持四种记录格式,分别是REDUNDANT、COMPACT、DYNAMIC和COMPRESSED,MySQL5.7默认是DYNAMIC格式。

下图是DYNAMIC行格式的示意图

 

记录头信息的格式示意图如下

部分字段含义

deleted_flag:顾名思义,该记录是否被删除的标志

min_rec_flag:B+树每层非叶子结点中最小的记录项的标志

n_owned: 页面中分组的

heap_on: 表示当前记录在页面堆中的相对记录

record_type: 表示当前记录的类型,0表示普通记录,1表示B+树非叶子结点的目录项记录,2表示Infimum记录,3表示Supremum记录。

next_record: 指向下一条记录,表示下一条记录的相对位置

 

记录示例

所有页面都有两条虚拟记录,即Infimum和Supremum。

Infimum代表页面中的最小的记录,而Supremum则代表页面中最大的记录。

 

数据排序

页内的记录串联成一个单向链表。

如果表有主键,会根据主键排序;

没主键有唯一非空索引,会根据该索引排序;

两者都没有,InnoDB会自动生成一个row_id列并根据该列进行排序。

 

页面格式

页是InnoDB管理存储空间的基本单位,一个页的大小一般是16K。

数据页面的结构如下图

File Header:页面通用信息,如当前页号、上一页/下一页页号

Page Header:页面的各种状态信息,如分组数量,记录数

User Records:记录的有序链表

Free Space:页面中尚未使用的空间

Page Directory:对User Records数据进行分组,减少遍历链表的次数,加速查找

File Tailer:校验页面数据是否完整

 

数据查找

页面内的数据是有序的单向链表。

假设单行数据128B,而单个磁盘页面大小可以是16KB,因此一个磁盘页面最多可以存放128条数据。这样挨个查找太慢。

可以利用有序链表的特性,对有序数据进行分组,记录每组的最大值,形成一个有序分组列表。先二分查找有序分组列表,再查找分组内的数据。

这里就会涉及的行记录的n_owned和页面的Page Directory了,InnoDB分组规则如下

1. Infimum记录所在的分组只能有一条记录

2. Supremum记录所在的分组拥有的记录数量为1~8条

3. 其它分组拥有的记录数量为4~8条

4. 分组指向组内ID最大的行。

 

 

查找过程

下图是简化的行记录和Page Directory。

 

在上图中查找ID=17的记录

1. 利用分组进行二分查找,

(1 + 5) / 2 = 3,分组3的最大ID为10,因此继续在右半区间查找

(3 + 5) / 2 = 4,分组最大的ID为15,17位于右半区间,又应为5 - 4 = 1,因此,17位于分组5

2. 组内顺序查找

在分组内遍历单向链表,查找到ID=17的记录

 

B+树索引

B+树数据结构

B树详解,这边随笔中介绍了B树的查找、插入、删除操作,可以深入理解B数的数据结构

 

CREATE TABLE `t_student` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`age` int NOT NULL DEFAULT '0' COMMENT '年龄',
`height` int NOT NULL DEFAULT '0' COMMENT '身高'
 PRIMARY KEY (`id`)
 KEY `age` (`age`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=COMPACT

 

 

 

聚簇索引

为了方便画图表示,下面是简化的聚簇索引各种记录格式

  

聚簇索引结构举例

 

从上图可以看出,

1)页面内记录按照主键增长的顺序构成一个单项链表

2)对于普通记录,则是一个按照主键有序的双向链表

二级索引

为了方便画图表示,下面是简化的二级索引各种记录格式

 

二级索引结构举例

从上图可以看出,

1)页面内记录按照二级索引age增长的顺序构成一个单项链表

2)对于普通记录,则是一个按照age有序的双向链表

3)普通记录并没没有包含完整的信息,而是<age,主键>的组合,需要取其它信息如height还需要进行回表

回表: 数据库根据索引(非主键)找到了指定的记录所在行后,还需要根据索引上保存的主键 ID 再次到数据块里获取数据。

 

建立索引的原则

1. 尽量使用占用空间少的索引

索引字段占用空间小,意味着单个页面可以存放更多的目录项目记录,使得B+数更加扁平,从而减少IO次数

2. 选择频繁作为查询条件的字段作为索引

频繁作为查询条件的字段作为索引,减少查询的时间,避免全表查询。

3. 选择区分度高的字段作为索引

例如性别只有男1女2两种情况,如果建立索引,目录项只有两条记录,意义不大。还增加了维护索引的成本。

4. 最左匹配原则

多个字段构成联合索引时,这几个字段的顺序十分重要。

假设有联合索引<a,b,c>

目录项记录是先按a排序,如果a相等再按b排序,如果a和b都相等,再按c排序。

如果查询条件只有(b,c),则改索引并不会生效。如果只有(a),那索引只是部分生效。

 

InnoDB Row Formats

《MySQL是怎么运行的》

 

标签:记录,链表,索引,查找,分组,MySQL,InnoDB,页面
From: https://www.cnblogs.com/amos01/p/16488759.html

相关文章

  • MySQL源码分析之SQL函数执行
    1.MySQL中执行一条SQL的总体流程2.SQL函数执行过程1.MySQL中执行一条SQL的总体流程一条包含函数的SQL语句,在mysql中会经过:客户端发送,服务器连接,语法解析,语句执行的......
  • 【MySQL】MySQL8确认哪些参数在使用以及来源
    在MySQL8中,参数可能来自不同的地方,确认有效的参数来自于哪里:SELECT variable_name, variable_sourceASsource, variable_path, set_time, set_userASUSER, set......
  • 【MySQL】MySQL8持久化系统变量
    set命令可以用于将某些全局系统变量持久化到数据目录中的mysqld-auto.cnf文件中,以影响后续启动的服务器操作。resetpersist从mysqld-auto.cnf中删除持久设置。在运行时持......
  • mysql在Linux与widows安装
    一、mysql的安装之前搭建linux下项目的发布,最后遗留的问题时数据库的迁移,如何从windows上迁移到linux上?这里首先进行mysql数据库的安装1、下载mysql安装包在这里下载的......
  • koa连接mysql数据库
    app.js中的代码:constKoa=require('koa2');constapp=newKoa();constport=5050;constRouter=require('koa-router');constrouter=newRouter();cons......
  • innodb buffer pool简介
    一、InnodbBufferPool简介BufferPool是Innodb内存中的的一块占比较大的区域,用来缓存表和索引数据。众所周知,从内存访问会比从磁盘访问快很多。为了提高数据的读取速......
  • Mysql 常用命令
    大纲命令执行事务STARTTRANSACTION;//开启事务UPDATE`Users`SETAccountId=0WHEREAccountIdisnullCOMMIT;//提交ROLLBACK;//回滚常见问题Q1.允......
  • mysql逻辑结构,存储结构
    宏观:库,存储在操作系统目录中表:  微观:段区页一个表就是一个段,mysql分配空间时至少分配一个区,每个区默认时1M(64个page页),mysql最小的IO单元就是PAGE(16KB) ......
  • mysql常用操作汇总
    工作中经常用会遇到这种情况,可以访问mysql所在的服务器,但是服务器端口不对外暴露(通常因为安全原因)。这时,操作数据库只能通过命令行和mysqlclient窗口来实现。我对这些操作......
  • mysql执行时的sql_mode设置
    查询当前MySQL的模式:select@@sql_mode;  根据需要设置模式,这里是将ONLY_FULL_GROUP_BY去掉:SETSESSIONsql_mode=(SELECTREPLACE(@@sql_mode,'ONLY_FULL_GROUP......