首页 > 数据库 >MySQL InnoDB 中的数据页

MySQL InnoDB 中的数据页

时间:2024-12-13 14:28:02浏览次数:7  
标签:存储 查询 索引 InnoDB MySQL 数据 节点

文章目录


1. 数据库的存储结构概述

在 MySQL 的 InnoDB 引擎中,记录是按照行来存储的,但是数据库的读取并不以行为单位,否则一次读取(也就是一次I/O操作)只能处 理一行数据,效率会非常低。因此在数据库中,不论读一行,还是读多行,都是将这些行所在的⻚进行加 载。也就是说,数据库管理存储空间的基本单位是⻚(Page)。

一个⻚中可以存储多个行记录(Row),同时在数据库中,还存在着区(Extent)、段(Segment)和表空 间(Tablespace)。行、⻚、区、段、表空间的关系如下图所示:

aa

从图中你能看到一个表空间包括了一个或多个段,一个段包括了一个或多个区,一个区包括了多个⻚,而一 个⻚中可以有多行记录。以下将详细解析这些存储单元的定义、关系以及作用。


1.1 表空间(Tablespace)

定义

表空间是 InnoDB 存储逻辑的最高层次单位,可以视为存储数据的容器。每个表空间由多个段、区和页组成。它将数据的物理存储与逻辑组织分离,便于管理和扩展。

表空间类型

  1. 系统表空间(System Tablespace)

    • 默认的共享表空间,包含数据字典、Undo 日志等核心信息。
    • 对所有表共享,位于 ibdata1 文件中。
  2. 独立表空间(File-Per-Table Tablespace)

    • 为每张表单独创建的表空间。
    • 文件扩展名为 .ibd,更容易进行备份和迁移。
  3. 临时表空间(Temporary Tablespace)

    • 用于存储临时表和内部操作。
    • 随服务重启自动清空。

与下层结构的关系

  • 表空间是段的集合。
    每个表或索引在表空间中分配一个或多个段。
  • 段通过区进行管理。
    每个段可包含多个区。
  • 区由固定数量的页组成。
    页是表空间中的实际数据存储单元。

表空间的扩展机制

  1. 自动扩展
    默认配置下,InnoDB 会动态调整表空间大小。
  2. 手动配置
    可通过 innodb_data_file_path 参数定义系统表空间文件的大小和增长策略。

1.2 段(Segment)

定义

段是表空间中的逻辑存储单元,用于组织表的数据和索引。每个表和索引都有独立的段。

段的类型

  1. 数据段(Data Segment)
    • 用于存储表中的数据。
  2. 索引段(Index Segment)
    • 用于存储 B+ Tree 索引。
  3. 回滚段(Rollback Segment)
    • 用于记录事务的 Undo 信息。

段的扩展策略

段通过分配新的区来扩展。每次扩展区的大小可能翻倍,以减少频繁分配的开销。

段与区的关系

  1. 一个段包含多个区。
  2. 一个区归属于唯一的段。

1.3 区(Extent)

定义

区是 InnoDB 分配数据存储的中间层,由一组连续的页组成。每个区的大小为 1MB,即包含 64 个 16KB 的页。

区分配机制

  1. 初始分配
    • 数据库创建时分配的区通常位于系统表空间的前部。
  2. 按需分配
    • 当段的现有区无法满足存储需求时,InnoDB 会分配新的区。

与上下游的关系

  • 区是段的一部分。
    每个区只属于一个段,数据逻辑上由段管理。
  • 区由页组成。
    页是区中的最小单位,存储具体数据行。

1.4 页(Page)

定义

页是 InnoDB 中的最小存储单元,每页默认大小为 16KB。数据最终存储在页中。

页的种类

  1. 数据页(Data Page)
    • 存储实际的行数据。
  2. 索引页(Index Page)
    • 用于存储索引条目。
  3. Undo 页(Undo Page)
    • 记录事务回滚所需的历史数据。
  4. 系统页(System Page)
    • 包含系统元信息。
  5. 事务页(Transaction Page)
    • 用于记录事务状态信息。

与区的关系

  • 每个区包含 64 个页。
  • 页是区的组成部分,但同时直接存储数据或索引。

2. InnoDB 数据页的深入解析


2.1 数据页的物理结构

page

数据页的组成部分

名称占用大小说明
File Header38字节文件头,描述页的信息
Page Header56字节页头,记录页的元信息,如页号和上级索引指针。
Infimum + Supremum26字节最小和最大记录,这是两个虚拟的行记录
User Records不确定用户记录,存储行记录内容
Free Space不确定空闲空间,页中还没有被使用的空间
Page Directory不确定页目录,存储用户记录的位置
File Trailer8字节文件尾,校验页是否完整

2.2 数据页中的行存储

数据页的核心功能是存储表中的行数据。在 InnoDB 中,行的存储布局经过精心设计,以优化存储空间和检索效率。

行记录格式

InnoDB 支持两种行存储格式:CompactRedundant

  • Compact 格式(默认)

    • 数据更紧凑,节省存储空间。
    • 仅存储必要的列值和指针信息。
    • 行数据前包含一个固定长度的变长字段偏移数组,用于快速解析列值的起始位置。
  • Redundant 格式

    • 早期版本的存储格式。
    • 每列有额外的开销,用于存储列长度和指针信息。

行记录的结构(Compact 格式)

每条行记录由以下部分组成:

  1. 记录头信息(Record Header)

    • 存储元信息,例如记录的长度、下一条记录的指针等。
  2. 隐藏列

    • DB_ROW_ID:系统生成的唯一行标识(如果表未定义主键)。
    • DB_TRX_ID:最后修改该行的事务 ID。
    • DB_ROLL_PTR:指向 Undo 日志的回滚指针。
  3. 用户数据列

    • 存储表中定义的实际列值。

行存储对比:Compact 与 Redundant

特性CompactRedundant
数据占用空间更少较多
列值解析效率较低
使用场景默认(推荐使用)兼容旧版本表

2.3 数据页满时的分裂与合并

数据页有固定的大小(通常为 16KB)。当页中的行数据达到存储极限时,InnoDB 会触发页分裂机制,将数据分散到新的页中。这一机制与 B+ Tree 的结构密切相关。

页分裂的触发条件

  • 主键插入顺序:当新插入的记录超过页的容量时,触发页分裂。
  • 非主键索引:对索引页的插入可能导致分裂,尤其是当索引值分布不均时。

页分裂的过程

  1. 新页分配:从当前段中分配一个空闲页,用作分裂后的目标页。
  2. 数据迁移:将当前页中约一半的数据迁移至新页。
  3. 父节点更新:更新上层索引页中的指针,记录新页位置。

页合并

当页中的数据量减少到一定程度(例如小于 50%)时,InnoDB 会尝试合并当前页与相邻页,以减少存储碎片并优化查询效率。


2.4 大字段(LOB)的存储机制

当列的数据长度超过数据页的存储容量时,InnoDB 会将其存储为大字段(LOB,Large Object)。

大字段的存储策略

  • INLINE 模式
    • 小型大字段直接存储在数据页中,避免额外的 I/O。
  • OFF-PAGE 模式
    • 超过指定大小的大字段,存储在单独的页中,并通过指针与主记录关联。

2.5 页分裂与合并的影响

查询效率的影响

  • 页分裂会导致树的深度增加,从而增加查询路径。
  • 页合并会减少树的深度,但在高并发写入时可能引发锁争用。

存储碎片的影响

频繁的分裂和合并可能导致存储碎片,从而降低存储利用率和检索性能。定期优化表(OPTIMIZE TABLE)可以缓解这一问题。


3. B+ Tree 查询逻辑的实现

在 MySQL InnoDB 中,索引的数据结构是基于 B+ Tree 实现的。B+ Tree 将数据分布在叶子节点上,通过多层索引加速查询。在这个过程中,数据页(Page)扮演着关键角色。以下将从 B+ Tree 的结构、查询逻辑、以及与数据页的关联逐步剖析。


3.1 B+ Tree 的结构特性

定义与特点

  1. 树结构

    • B+ Tree 是一种平衡的多叉树,每个节点可以有多个子节点。
    • 根节点到叶子节点的路径长度相同。
  2. 节点分布

    • 非叶子节点存储索引键值和指向子节点的指针。
    • 叶子节点存储实际数据(或指向数据的指针)。
  3. 顺序访问

    • 所有叶子节点通过链表连接,支持范围查询和排序操作。
  4. 分裂与合并

    • 节点满时分裂;节点数据过少时合并。

B+ Tree 的优势

  • 高扇出率:节点中可以存储多个索引键,树的深度较小。
  • 磁盘友好:每次 I/O 操作加载一个完整的页,减少磁盘访问次数。
  • 有序性:天然支持范围查询和排序。

B+ Tree的结构图

tree

B+树记录检索流程

在一棵B+树中,每个节点都是一个⻚,每次新建节点的时候,就会申请一个⻚空间。同一层上的节点之 间,通过⻚的结构构成一个双向的链表(⻚文件头中的两个指针字段)。非叶子节点,包括了多个索引行, 每个索引行里存储索引键和指向下一层⻚面的⻚面指针。最后是叶子节点,它存储了关键字和行记录,在节 点内部(也就是⻚结构的内部)记录之间是一个单向的链表,但是对记录进行查找,则可以通过⻚目录采用 二分查找的方式来进行。

  1. 首先是从B+树的根开始,逐层检索,直到找到叶子节点,也就是找到对应的数据⻚为止

  2. 将数据⻚加载到内存中,⻚目录中的槽(slot)采用二分查找的方式先找到一个粗略的记录分组

  3. 然后再在分组中通过链表遍历的方式查找记录。


3.2 数据页在 B+ Tree 查询中的角色

B+ Tree 的每个节点对应于一个 页(Page),根据节点的功能不同,可分为以下几类:

  1. 根页(Root Page)

    • 位于树的最顶部,保存全局索引范围的入口点。
    • 查询从根页开始,逐层向下遍历。
  2. 非叶子页(Non-Leaf Page)

    • 存储子节点的索引范围和指针,用于指导查询方向。
  3. 叶子页(Leaf Page)

    • 存储实际数据或指向数据的指针。
    • 所有叶子页通过链表相连,支持顺序扫描。

页与索引条目的关系

  • 每个非叶子页中的索引条目包含一个键值范围和指向下层页的指针。
  • 叶子页的条目记录主键值与行数据的位置(或直接存储行数据)。

3.3 查询逻辑详解

查询路径示意图

假设有如下 B+ Tree 索引树,表示一张表的主键索引:

在这里插入图片描述

查询主键值 60 的流程如下:

  1. 从根页开始

    • 比较查询值 60 和根页索引值 50,判断其位于右子树中。
    • 跳转到右子节点页(Index Page (75))。
  2. 访问非叶子页

    • 在右子节点页中,60 小于 75,定位到左子节点(叶子页)。
  3. 访问叶子页

    • 在叶子页中,扫描主键值,找到匹配的记录。

通过页目录加速定位

InnoDB 数据页中的**页目录(Page Directory)**可以进一步优化叶子页内的查询效率。页目录将数据按偏移量分段,允许通过二分查找快速定位具体行数据。

主键索引与辅助索引查询

  1. 主键索引查询

    • 主键索引是聚簇索引(Clustered Index),叶子节点直接存储行数据。
    • 查询时路径:根页 -> 非叶子页 -> 叶子页 -> 数据行
  2. 辅助索引查询

    • 辅助索引的叶子节点存储主键值,而非行数据。
    • 查询时路径:
      • 第一步:通过辅助索引定位主键值。
      • 第二步:回到主键索引查找实际数据(称为回表)。

3.4 页缓存(Buffer Pool)的作用

在查询过程中,InnoDB 使用**缓冲池(Buffer Pool)**将频繁访问的页保存在内存中,减少磁盘 I/O。

缓冲池的工作机制

  1. 缓存读取
    • 查询页时,先从缓冲池中查找;如果页不存在,则从磁盘加载到缓冲池。
  2. 缓存替换
    • 使用 LRU(最近最少使用)算法管理缓冲池中的页。

性能优化建议

  • 增加 innodb_buffer_pool_size 参数以适配更大的缓冲池。
  • 通过 SHOW ENGINE INNODB STATUS 分析缓冲池的命中率。

4. 最佳实践

在深入理解了 InnoDB 的存储结构及其在查询、插入中的表现后,可以总结以下关键点和最佳实践,这些建议可以帮助开发者优化数据库设计,提高性能。


4.1 优化数据页

1. 主键设计

  • 使用自增整数主键,避免主键长度过长。
  • 避免使用随机值(如 UUID)作为主键,减少页分裂几率。

2. 合理选择索引

  • 为高频查询字段添加索引,但要避免过多索引增加写入开销。
  • 使用覆盖索引优化性能,减少不必要的回表。
  • 定期检查和重建索引,清理碎片。

3. 数据分布管理

  • 控制插入顺序,尽量保证数据的逻辑顺序与物理存储顺序一致。
  • 定期执行 OPTIMIZE TABLE,减少存储碎片,提高页利用率。

4. 参数调优

  • 调整 innodb_buffer_pool_size,尽可能提高缓冲池命中率,减少磁盘 I/O。
  • 根据业务场景调整 innodb_page_size,为大数据场景选择 32KB 页,为小型数据选择 16KB 页。
  • 使用 SHOW ENGINE INNODB STATUS 和性能分析工具(如 Percona Toolkit)监控表和页的使用情况。

4.2 从数据页角度优化查询

1. 充分利用缓冲池

  • 缓冲池作为数据页的内存缓存,命中率直接影响性能。
  • 调整缓冲池大小时,应确保其占用内存不超过服务器物理内存的 75%,避免系统交换空间(swap)的使用。

2. 减少页分裂与回表操作

  • 保证主键连续性和顺序性,减少页分裂次数。
  • 对经常查询的字段设计覆盖索引,避免回表操作。

3. 提前规划分区

  • 对存储需求巨大的表,提前设计分区表。
  • 结合分区键和索引优化,减少不必要的全表扫描。

5. 总结

  • 理解数据页:数据页是 InnoDB 存储的基础,设计优化时需关注其分裂、合并及数据分布。
  • 掌握存储结构:表空间、段、区、页的管理方式决定了数据存储的灵活性和性能表现。
  • 优化索引使用:根据查询需求合理设计索引,减少不必要的回表操作。
  • 配置调优:结合业务场景调整页大小、缓冲池大小等参数,提升查询性能。

关注我

标签:存储,查询,索引,InnoDB,MySQL,数据,节点
From: https://blog.csdn.net/tatasix/article/details/144445789

相关文章

  • MySQL InnoDB 的锁机制
    文章目录1.引言2.锁的基础概念2.1什么是锁?2.2锁的核心实现原理2.3InnoDB中锁的分类3.悲观锁与乐观锁3.1悲观锁详解3.2乐观锁详解3.3两种锁策略的性能对比4.系统锁4.1系统锁的使用场景4.2系统锁的实现方式4.3系统锁的优缺点5.表锁5.1表锁的内部实现5.2......
  • 达梦数据库系列教程01---数据库备份与还原
    一、备份数据库1、右键服务器管理,打开如下的页面,选配置,再点转换2、归档配置修改,选“归档”,填一个归档目档  3、再次选择“系统管理”,将态管理选中“打开”,再点转换 4、备份---》库备份----》新建备份  二、还原数据库 ......
  • 【深度学习|地学应用之遥感图像切块】海量的遥感数据为深度学习的地学应用提供了基础,
    【深度学习|地学应用之遥感图像切块】海量的遥感数据为深度学习的地学应用提供了基础,那么大幅遥感影像如何输入到深度学习中进行模型训练呢?patch块的生成,附代码【深度学习|地学应用之遥感图像切块】海量的遥感数据为深度学习的地学应用提供了基础,那么大幅遥感影像如何输入......
  • UE4脸部捕捉 LiveLink 数据
     enumclassEARFaceBlendShape:uint8{ //Lefteyeblendshapes EyeBlinkLeft, EyeLookDownLeft, EyeLookInLeft, EyeLookOutLeft, EyeLookUpLeft, EyeSquintLeft, EyeWideLeft, //Righteyeblendshapes EyeBlinkRight, EyeLookDownRight, EyeLookInRight, EyeLookOut......
  • 【java毕设 python毕设 大数据毕设】基于springboot的旧物回收管理系统的设计与实现
    ✍✍计算机编程指导师⭐⭐个人介绍:自己非常喜欢研究技术问题!专业做Java、Python、小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。⛽⛽实战项目:有源码或者技术上的问题欢迎在评论区一起讨论交流!⚡⚡Java实战|SpringBoot/SSMPython实战项目|Django微信小程......
  • 【java毕设 python毕设】基于springboot的考务管理系统的设计与实现 【附源码+数据库+
    ✍✍计算机编程指导师⭐⭐个人介绍:自己非常喜欢研究技术问题!专业做Java、Python、小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。⛽⛽实战项目:有源码或者技术上的问题欢迎在评论区一起讨论交流!⚡⚡Java实战|SpringBoot/SSMPython实战项目|Django微信小程......
  • Amazon Aurora 中的数据表同步到 Amazon S3
    在现代数据处理架构中,将数据从关系型数据库迁移到对象存储是一个常见的需求。本文将详细介绍如何使用AWSDatabaseMigrationService(DMS)将AmazonAurora中的表数据同步到AmazonS3。前提条件在开始之前,请确保你已经:创建了一个AmazonAurora数据库实例。创建......
  • 关于数据隐藏:为什么要进行数据隐藏?如何在C++中实现数据隐藏?以及数据隐藏对面向对象编
    一、为什么要进行数据隐藏?数据隐藏可以提高程序的安全性和可维护性。可以将数据成员声明为私有或受保护,可以防止外部代码直接访问和修改这些数据,从而减少错误的发生。同时,数据隐藏也使得类的内部实现细节对外部不可见,这样在修改类的内部实现时,不会影响外部代码的使用。二、......
  • 【数据库开发】反范式化的应用场景与实践
    在数据库设计中,“范式化”是一种减少冗余、确保数据一致性的原则,但在实际应用中,有些场景却不得不违背这一原则,以换取性能的提升。反范式化(Denormalization)就是在特定性能需求下的一种权衡策略。今天我们将从理论到实践,全面解析反范式化的概念、应用场景、具体策略以及它带来的风险......
  • Windows Server 上启用存储空间中的重复数据删除功能(Data Deduplication),你可以按照以
    WindowsServer上启用存储空间中的重复数据删除功能(DataDeduplication),你可以按照以下步骤在PowerShell中配置。1.启用重复数据删除功能首先,确保你的系统已经安装了DataDeduplication功能。如果没有安装,可以使用以下命令进行安装:powershellCopyCodeInstall-WindowsFea......