Mysql进阶索引篇02——InnoDB存储引擎的数据存储结构(一)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 前面我们已经剖析了mysql中InnoDB与MyISAM索引的数据结构,了解了B+树的设计思想、原理,并且介绍了B+树与Hash结构、平衡二叉树、AVL树、B树等的区别和实际应用场景。页和页之间并不一定在物理上相连,只是在逻辑上使用双向链表关联。指针、记录究竟是如何存储的呢?其实这就需要联系我们之前提到的行格式了。数据查找在页目录中二分法快速定位到槽,上面的过程都与页的内部结构相关,本文将详细的阐述。

前言


前面我们已经剖析了mysql中InnoDBMyISAM索引的数据结构,了解了B+树的设计思想、原理,并且介绍了B+树与Hash结构平衡二叉树AVL树B树等的区别和实际应用场景。

页和页之间并不一定在物理上相连,只是在逻辑上使用双向链表关联。指针、记录究竟是如何存储的呢?其实这就需要联系我们之前提到的行格式了。数据查找在页目录中二分法快速定位到,上面的过程都与页的内部结构相关,本文将详细的阐述。

这篇文章将对InnoDB引擎的数据存储结构介绍,带大家熟悉数据库的页的存储结构与行格式,为之后的调优做准备。


1.数据库的存储结构:页

索引实际上是存储在文件上的,确切的说是存储在页结构中的。存储引擎负责数据的读、写操作,不同的存储引擎的数据格式可能不同。本文所介绍的数据库存储结构基于Mysql的InnoDB存储引擎。这也是我们实际工作中所使用的。

1.1 磁盘与内存交互的基本单位:页

InnoDB将数据划分为若干页,Mysql页的默认大小是16kb.可以使用下面的命令进行查看。

在sql server中,页的默认大小是8kb。Oracle中使用块*(Block)的概念来作为磁盘与内存的基本交互单位,块的大小可以是2kb,4kb,8kb,16kb,32kb和64kb。


这里我们强调,mysql中磁盘与内存交互的基本单位是页,这表示我们在磁盘与内存之间进行数据交互,最少是一页,并且每次交互都是整数页。即使我们数据存储只存储了一行,数据库I/O的操作单位也是一页。这样设计其实也是为了提高效率,毕竟I/O的时间消耗很大,不可能读、写一次数据就进行一次磁盘的I/O操作。


1.2 页上层结构

页的上层结构是,一个区会分配64个连续页,区的大小正好是1MB(16kb * 64)。

段由一个区或多个区组成。段是数据库的分配单位,比如我们创建一个表,就会创建一个表段,创建一个索引,就会创建一个索引段。总而言之,不同类型的数据库对象对应不同类型的段。


这里我们举一个例子,部队中能够与敌军战斗的基本单位是一个兵,就像数据库中内存与磁盘交互的基本单位是一个页。但是一场战争派出去的不可能只是一个兵,而是更大的单位,比如师。对应的,数据库内存分配的最小单位是一个块。


表空间(table space)是一个逻辑容器。表空间中存储的是一个或者多个段,每个段只能属于一个表空间。表空间又可以分为系统表空间,用户表空间,撤销表空间、临时表空间等。


2.页的内部结构

常见的页有数据页(保存b+树节点)、系统页Undo页事务数据页

页可以划分为如下的七个结构。

这七个结构的作用如下。

为了方便大家的理解,我们将他们归纳为三个部分,进行讲解。

2.1 文件头与文件尾

File Header与File Trailer主要是用于描述页的通用信息,用于页与页的交互或者数据的校验等。

  • FILE_PAGE_OFFSET:记录页编号,InnoDB可以通过页号唯一确定一个页。


FILE_PAGE_TYPE:代表当前页的类型,比如FILE_PAGE_UNDO_LOG(Undo日志页)、FILE_PAGE_TYPE_SYS(系统页)、FILE_PAGE_INDEX(索引页/数据页)。


FILE_PAGE_PREV与FILE_PAGE_NEXT上一页与下一页。


FILE_PAGE_SAPCE_OR_CHKSUM:校验和,对于一个较长的字符串,我们可以通过算法将其计算得到较短的字符串,即校验和,当我们需要比较两个长的字符串是否相等时,就比较他们校验和即可。同样我们也可以用校验和比较两个页是否相等。

文件尾页同样有校验和,它们是对应的。当我们对磁盘进行数据更新的刷盘执行I/O时,如果由于断电等原因导致数据传输中断,很可能一个页没有操作完。而页是数据库中磁盘与内存交互的基本单位,为了能够保证一致性,我们需要回滚或者将未写完的数据写完。我们如何判断是否写完呢?就是通过校验和。

具体的过程是:在内存向磁盘写入数据时,先更新File Header中的校验和,如果文件未正常写完,头尾校验和会不一致,如果未刷盘的数据有记录,就继续刷完,否则回滚。


FILE_PAGE_LSN:日志序列号,记录文件最后修改时对应的日志序列位置。尾部也有该字段,同样是为了校验页面的完整性。


2.2 记录部分:空闲空间、最大/小记录、用户记录

在最开始,我们会将已存储的数据按照行格式放到User Records,每插入一个数据,就会从Free Space申请一个记录大小的空间划分到User Records,直到Free Space都被转化为User Records空间,会申请一个新的页。User Records中的数据是按照单链表进行连接的。具体细节我们将在介绍行格式的用户头信息时介绍。


在介绍最小记录和最大记录之前,我们先思考一个问题,有必要对记录大小进行比较吗?当然是有必要的,因为我们的节点都是进行排序的。既然需要排序,就需要进行大小的比较了。那么,最大记录和最小记录的作用是什么呢?实际上,它就相当于记录的头、尾节点,这里我们先简单介绍,后面我们介绍完行格式,大家会对这部分理解更为深刻。在mysql中,最小记录与最大记录的格式非常简单,可以参考下图。

2.3 页目录与页头

page_decotory主要是为了方便数据进行二分查找。页目录是不是一开始就生成的呢?比如我们有1000条记录,是不是一开始就按照主键生成这1000条记录的页目录?这样做对于存储的占用显然是很高的。

实际上,mysql数据库做法如下。


将每页所有记录(包括最小记录与最大记录,不包含已删除记录)进行了分组,每个组取一个记录放入页目录中,占一个槽位(slot).最小记录单独为1组,最大记录所在组一般是有1-8条记录,其它组一般有4-8条记录。

每组的最后一条记录会存储一个n_owned属性,代表该组有几个记录。

页目录用于存储每组最后一个记录的地址偏移量。

下图表示了这个过程,其中每个记录的第一个字段就是n_owned.

现在我们已经知道页目录是如何生成的了,那么我们如何利用页目录进行数据的查找呢?实际上就是利用二分法对需要查找的数据与页目录中数据进行比较。比如一个数据确定比槽2的更大,比槽3的更小,那就可以去槽3所链接的分组4进行查找了。它会从槽2所链接的分组3最后一个记录指针链接到分组4的第一个元素,然后进行遍历查找。

接下来我们看看page header中记录了什么信息。这些信息大概了解下,主要是页的内部结构的一些信息。

其中PAGE_DIRECTION记录当前新插入记录是需要在上一条记录的前面还是后面插入。

2.4 从存储角度看普通索引和唯一索引有什么不同

我们到目前为止已经了解了页的内部结构和索引的数据结构。接下来我们深入思考一个问题。

普通索引和唯一索引有什么不同?

唯一索引指的是对索引字段加了唯一约束的索引,因此该字段不会重复。我们学习了页的存储结构以后知道,一般一个页默认大小是16kb,可以存放上千条记录,而且这些元素的存放是有序的,元素之间通过指针相连接。因此,普通索引一般只是在找到第一个元素后再多往后进行几次查找即可,其时间消耗并不大(真正消耗时间的是磁盘I/O)。


3.InnoDB行格式

3.1 行格式简介与操作sql

行格式就是记录的存储格式。

行格式一般有CompactDynamicCompressedRedundant几种。

可以使用如下的查询语句查询Mysql数据库的默认行格式。在mysql8与mysql5.7中,默认行格式都是dynamic

可以使用下列语句查询某个表实际使用的行格式。

使用如下语句可以在创建表时指定其行格式。

修改表的行格式。

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
14天前
|
存储 缓存 关系型数据库
✅InnoDB为什么使用B+树实现索引?
InnoDB使用B+树实现索引,因其具备平衡特性、所有数据存储在叶子节点利于范围查询和排序,且非叶子节点仅含索引关键字,能存储更多数据,减少IO操作并优化缓存利用率。B+树与哈希索引的区别在于,后者适用于等值查询但不支持范围查询和排序,且磁盘访问效率较低。相比于红黑树和B树,B+树更适合数据库索引需求。
|
19天前
|
存储 监控 关系型数据库
MySQL 参数innodb_read_io_threads
`innodb_read_io_threads` 是 MySQL 数据库中 InnoDB 存储引擎的一个配置参数,它用于指定后台线程池中用于处理读取 I/O 请求的线程数量。InnoDB 存储引擎负责管理数据库的物理存储和检索,是 MySQL 最常用的存储引擎之一。 ### 参数说明 - **名称**: `innodb_read_io_threads` - **默认值**: 4 - **范围**: 1 到 64 - **动态修改**: 不能动态修改(需要重启服务器) - **适用版本**: MySQL 5.6 及以上版本 ### 作用 `innodb_read_io_threads`
|
16天前
|
SQL 算法 关系型数据库
✅Innodb加索引,这个时候会锁表吗?
MySQL 5.6 引入 Online DDL 技术,允许在创建或删除 InnoDB 索引时不阻塞其他会话,减少了锁定和性能影响。不同 DDL 操作支持不同方式,如 COPY、INSTANT 和 INPLACE,具体见官方文档。虽然 Online DDL 可减少阻塞,但可能在索引构建期间仍有锁定,建议在非高峰时段执行并做好测试和规划。MySQL 5.6 之前的 DDL 操作会导致表锁定,而 Online DDL 旨在减少这种阻塞,但并非所有 DDL 语句都适用。了解各种算法如 COPY、INPLACE 和 INSTANT,以及它们的工作原理,有助于优化 DDL 操作。
|
21天前
|
NoSQL 关系型数据库 MySQL
B+树 和 跳表 的结构及区别,不同的用途【mysql的索引为什么使用B+树而不使用跳表?】
B+树 和 跳表 的结构及区别,不同的用途【mysql的索引为什么使用B+树而不使用跳表?】
70 2
|
21天前
|
存储 缓存 关系型数据库
MySQL结构流程,看这一篇就够了!
MySQL结构流程,看这一篇就够了!
|
21天前
|
运维 负载均衡 关系型数据库
MySQL高可用解决方案演进:从主从复制到InnoDB Cluster架构
MySQL高可用解决方案演进:从主从复制到InnoDB Cluster架构
|
21天前
|
存储 SQL 关系型数据库
mysql中MyISAM和InnoDB的区别是什么
mysql中MyISAM和InnoDB的区别是什么
19 0
|
5天前
|
存储 NoSQL 关系型数据库
mysql 数据库 基本介绍
mysql 数据库 基本介绍
|
21小时前
|
SQL 关系型数据库 MySQL
mysql 数据库导出导入到本地文件
mysql 数据库导出导入到本地文件
|
1天前
|
Prometheus 监控 关系型数据库
数据库同步革命:MySQL GTID模式下主从配置的全面解析
数据库同步革命:MySQL GTID模式下主从配置的全面解析
7 0