Mysql数据在磁盘上的存储结构

一. 前言

一行数据的存储格式大致如下所示:

变长字段的长度列表,null值列表,数据头,column01的值,column02的值,column0n的值…

二. 变长字段

在MySQL里有一些字段的长度是变长的,是不固定的,比如VARCHAR(255)之类的这种类型的字段,实际上他里面存放的字符串的长度是不固定的,有可能是“hello”这么一个字符串,也可能是“hello word”这么一个字符串。

  • 示例1
格式VARCHAR(10)CHAR(1)CHAR(1)
数据helloaa
存储方式0x05 null值列表 数据头 hello a a
  • 示例2
    多个变长字段, 是逆序存储
格式VARCHAR(10)VARCHAR(5)VARCHAR(20)CHAR(1)CHAR(1)
数据helloa2aa3aa
存储方式0x05 0x02 0x03 null值列表 数据头 hello a a
  • 为什么要逆序存储.
在 MySQL 中,对于变长字段(如 VARCHAR),其长度信息在存储时确实可能以逆序方式存储,这主要涉及到存储格式和性能优化的考量。这个特性尤其在早期版本的 MySQL 中比较明显,而在新版本中,由于存储格式的改进和优化,这种差异可能不那么直观。以下是一些可能导致逆序存储长度信息的原因:### 1. 存储效率在某些场景下,将变长字段的长度信息以逆序方式存储可以提高存储效率。例如,如果一个表包含多个变长字段,MySQL 需要在记录的开始处存储这些字段的长度信息。通过逆序存储这些长度信息,MySQL 可以更有效地处理记录中字段值的增减变化,因为这样做可以减少因字段长度变化而导致的数据移动。### 2. 记录格式MySQL 中,尤其是 InnoDB 存储引擎,采用了多种记录格式(如 COMPACT 和 REDUNDANT)。在某些记录格式中,字段长度的存储方式可能被设计为逆序,部分原因是为了优化记录的解析过程。在解析一条记录时,从记录的末尾开始可以更快地定位到可变长度字段的实际内容,尤其是在需要跳过某些字段以访问特定字段时。### 3. 兼容性和历史原因MySQL 的不同版本和存储引擎在记录格式和存储策略上可能有所不同。一些设计决策,包括字段长度信息的存储方式,可能受到向后兼容性和历史遗留问题的影响。随着 MySQL 版本的发展,存储格式和算法不断优化,但在一些情况下,逆序存储长度信息的方式可能被保留下来,以确保数据的一致性和有效的性能表现。

三.mysql innodb_default_row_format 可以配置那些值, 有什么区别

在MySQL中,innodb_default_row_format选项指定了InnoDB表创建时的默认行格式。这个设置对于新创建的表非常重要,因为它影响了数据的存储方式、空间利用率和性能。innodb_default_row_format可以配置为以下几个值,每个值代表不同的行格式:

可配置的值及其区别

  1. Redundant

    • 这是早期版本的InnoDB行格式,默认使用在MySQL 5.0及更早版本中。
    • 它提供了最基本的特性集合,但在空间利用率和性能方面并不是最优的。
    • Redundant行格式支持较小的最大行大小和较少的数据类型优化。
  2. Compact

    • 从MySQL 5.0版本引入,是一个比Redundant更高效的行格式,旨在改进空间利用率。
    • 它减少了头信息的尺寸,并采用了更高效的方式存储NULL值和可变长度字段。
    • 对于许多应用而言,Compact是一个好的默认选择,因为它提供了较好的空间效率而不牺牲太多性能。
  3. Dynamic

    • 在MySQL 5.7.9及以后版本中,Dynamic成为了默认的行格式。
    • 它解决了Compact格式中一些限制,特别是关于BLOB和TEXT类型字段的更高效存储。在Dynamic格式中,这些类型的字段只在行中存储20字节的指针,实际数据存储在外部页面。
    • Dynamic行格式提供了更好的空间利用率,特别是对于包含大量BLOB或TEXT字段的表。
  4. Compressed

    • Compressed行格式允许对整行数据进行压缩,进一步节省存储空间。
    • 它特别适用于那些磁盘空间成本高昂或者需要存储大量历史数据的环境。
    • 使用Compressed格式可能会对CPU资源产生额外负担,因为需要在读写时进行压缩和解压缩操作。

选择合适的行格式

选择哪种行格式取决于具体的应用需求。DynamicCompressed格式在空间利用率方面提供了显著的优势,特别是对于包含大量长文本或BLOB字段的表。然而,Compressed格式可能会引入一定的性能开销。对于大多数应用,Dynamic行格式提供了一个很好的平衡点,特别是在MySQL 5.7.9及以后版本中,它成为了默认选择。

配置方法

在MySQL中,你可以通过几种方式查询默认的行格式(row format)。默认的行格式是指当你创建一个新表且没有指定行格式时,MySQL所使用的行格式。下面介绍两种常见的方法来查询默认行格式:

    1. 查看全局变量

MySQL允许你通过查询全局系统变量来了解当前的默认行格式。你可以使用以下SQL命令查询默认的行格式:

SHOW VARIABLES LIKE 'innodb_default_row_format';

这条命令会返回innodb_default_row_format变量的值,该值表示InnoDB存储引擎默认使用的行格式。可能的返回值包括RedundantCompactDynamic等。

    1. 查看服务器配置文件

MySQL的默认行格式也可以在服务器的配置文件(通常是my.cnfmy.ini,具体取决于你的操作系统)中进行设置和查看。在配置文件中搜索innodb_default_row_format这一行。例如:

[mysqld]
innodb_default_row_format=dynamic

如果在配置文件中设置了该参数,它将决定默认的行格式。请注意,更改配置文件需要重启MySQL服务器才能生效。

  • 附加信息

  • MySQL版本的影响:不同版本的MySQL可能有不同的默认行格式设置。例如,在MySQL 5.7.9及以后版本中,默认行格式是DYNAMIC

  • 修改默认行格式:你可以通过修改配置文件或设置全局变量的方式来更改默认的行格式,但请注意更改默认行格式可能会影响新创建表的性能和存储效率。

  • 表级行格式设置:即使更改了默认行格式,你仍然可以在创建表时通过ROW_FORMAT选项指定特定表的行格式,这将覆盖全局默认设置。

四. NULL值列表

对所有的NULL值,不通过字符串在磁盘上存储,而是通过二进制的bit位来存储,一行数据里假设有多个字段的值都是NULL,那么这多个字段的NULL,就会以bit位的形式存放在NULL值列表中。

  • 示例
    建表语句
CREATE TABLE customer (name VARCHAR(10) NOT NULL,address VARCHAR(20),gender CHAR(1),job VARCHAR(30),school VARCHAR(50)
) ROW_FORMAT=COMPACT;

上面那个表就是一个假想出来的客户表,里面有5个字段,分别为name、address、genderjob、school,就代表了客户的姓名、地址、性别、工作以及学校。

其中有4个变长字段,还有一个定长字段,然后第一个name字段是声明了NOT NULL的,就是不能为NULL,其他4个字段都可能是NULL的。

存储数据: “jack NULL m NULL xx_school”

  1. 先看变长字段长度列表
    一共有4个变长字段, 变长字段的值是NULL,就不用在变长字段长度列表里存放他的值长度了. 所以在上面那行数据中,只有name和school两个变长字段是有值的,把他们的长度按照逆序放在变长字段长度列表中就可以了

0x09 0x04 NULL值列表 头信息 column1=value1 column2=value2 … columnN=valueN

  1. NULL值列表
    允许值为NULL,不是说一定值就是NULL了,只要是允许你为NULL的字段,在这里每个字段都有一个二进制bit位的值,如果bit值是1说明是NULL,如果bit值是0说明不是NULL。
    比如上面4个字段都允许为NULL,每个人都会有一个bit位,这一行数据的值是“jack NULL m NULL xx_school”,然后其中2个字段是null,2个字段不是null,所以4个bit位应该是:1010
    NULL值列表存放的时候,他一般是8个bit位的倍数,如果不足8个bit位就高位补0

0x09 0x04 00000101 头信息 column1=value1 column2=value2 … columnN=valueN

五. 数据头 (40个bit)

数据头是用来描述这行数据

这40个bit位里,第一个bit位和第二个bit位,都是预留位,是没任何含义的

一个bit位是delete_mask,他标识的是这行数据是否被删除了

1-23 : delete_mask4: min_rec_mask5-9 : n_owned10-23: heap_no24-26: record_type27-40: next_record
预留位是否被删除在B+树里每一层的非叶子节点里的最小值, 用于指示是否有记录具有相同的键值位于它之后, 用于优化记录的读取在B+树索引结构中,一个索引记录(record)“拥有”的相邻记录数当前这行数据在记录堆里的位置这行数据的类型: 0代表的是普通类型,1代表的是B+树非叶子节点,2代表的是最小值数据,3代表的是最大值数据指向他下一条数据的指针

六. 字符串存储(根据字符集编码存储)

表结构:

CREATE TABLE customer (name VARCHAR(10) NOT NULL,address VARCHAR(20),gender CHAR(1),job VARCHAR(30),school VARCHAR(50)
) ROW_FORMAT=COMPACT;

存储数据: jack NULL m NULL xx_school

真实存储类似 (非最终存储结构, 字符串尚未编码):
0x09 0x04 00000101 0000000000000000000010000000000000011001 jack m xx_school

字符串根据数据库指定的字符集编码,进行编码之后再存储的

编码后的格式(非最终存储结构):
0x09 0x04 00000101 0000000000000000000010000000000000011001 616161 636320 6262626262

在实际存储一行数据的时候,会在他的真实数据部分,加入一些隐藏字段

  1. 首先有一个DB_ROW_ID字段,这就是一个行的唯一标识,是他数据库内部的一个标识,不是你的主键ID字段。
    如果没有指定主键和unique key唯一索引的时候,他就内部自动加一个ROW_ID作为主键。

  2. 接着是一个DB_TRX_ID字段,这是跟事务相关的,他是说这是哪个事务更新的数据,这是事务ID

  3. 最后是DB_ROLL_PTR字段,这是回滚指针,是用来进行事务回滚的

实际一行数据存储(最终)
0x09 0x04 00000101 0000000000000000000010000000000000011001 00000000094C(DB_ROW_ID)00000000032D(DB_TRX_ID) EA000010078E(DB_ROL_PTR) 616161 636320 6262626262

七. 行溢出

在MySQL的InnoDB存储引擎中,“行溢出”(Row Overflow)是指一行数据过大,无法完全存储在一个数据库页(Page)中时发生的情况。这通常发生在包含大量文本或二进制数据(如BLOB或TEXT类型字段)的行上。InnoDB的页面大小通常为16KB,当一行数据的总大小超过这个限制时,就会发生行溢出。

  • 为什么会有行溢出?
    InnoDB使用B+树存储机制来组织数据表和索引。每个B+树节点(页)有一个最大的空间限制,默认情况下是16KB。大多数行数据都能完整地存储在单个页内,但当遇到特别大的字段值时,如大文本或BLOB字段,整行数据可能无法适应单个页的空间限制。

  • 行溢出的处理机制:
    当InnoDB遇到一个无法适应单个页的大行时,它采用的策略是将主要的行数据保存在原始页中,但会将大字段的一部分或全部移动到其他页(溢出页)上。原始记录页中的大字段位置会被一个指针替代,这个指针指向存储实际数据的溢出页。

  • 行溢出的影响:

性能影响:访问涉及行溢出的数据可能需要额外的磁盘I/O操作,因为需要读取一个或多个额外的溢出页来获取完整的行数据。这种额外的I/O开销可能会导致性能下降,特别是在大量随机访问的场景中。

空间利用:虽然行溢出机制允许InnoDB表存储大于页面大小的行数据,但这种方式可能导致存储空间的利用率不是很高。溢出页可能不会完全填满,特别是当存储非常大的字段时。

  • 如何管理行溢出:

适当的表设计:尽可能避免在表中使用大量的大型字段。如果应用确实需要存储大量文本或二进制数据,考虑将这些数据分割成较小的部分,或者使用外部存储系统。

选择合适的行格式:对于包含大字段的表,使用DYNAMIC或COMPRESSED行格式可能更合适。这些行格式提供了更高效的行溢出数据管理机制。

监控和优化:使用工具和命令(如SHOW TABLE STATUS)来监控表的大小和行格式,以及定期进行数据库优化,可以帮助管理和减轻行溢出的影响。

八. 数据页

MySQL中进行数据操作的最小单位应该是数据页
执行crud的时候,都会从磁盘上加载数据页到Buffer Pool的缓存页里去,然后更新了缓存页后,又会刷新回磁盘上的数据页里去

数据页拆分成了很多个部分,大体上来说包含了文件头、数据页头、最小记录和最大记录、多个数据行、空闲空间、数据页目录、文件尾部。

  • 数据区域存储占比

其中文件头占据了38个字节,
数据页头占据了56个字节,
最大记录和最小记录占据了26个字节,
数据行区域的大小是不固定的,
空闲区域的大小也是不固定的,
数据页目录的大小也是不固定的,
然后文件尾部占据8个字节。

九. 表空间

表都是有对应的表空间的,每个表空间就是对应了磁盘上的数据文件,在表空间里有很多组数据区,一组数据区是256个数据区,每个数据区包含了64个数据页,是1mb

表空间的第一组数据区的第一个数据区的头三个数据页,都是存放特殊信息的;

表空间的其他组数据区的第一个数据区的头两个数据页,也都是存放特殊信息的

在这里插入图片描述

创建的表,其实都是有一个表空间的概念,在磁盘上都会对应着“表名.ibd”这样的一个磁盘数据文件
在物理层面,表空间就是对应一些磁盘上的数据文件。

有的表空间,比如系统表空间可能对应的是多个磁盘文件,有的我们自己创建的表对应的表空间可能就是对应了一个“表名.ibd”数据文件。

然后在表空间的磁盘文件里,会有很多很多的数据页,

一个表空间里包含的数据页实在是太多了,不便于管理,所以在表空间里又引入了一个数据区的概念,英文就是extent

一个数据区对应着连续的64个数据页,每个数据页是16kb,所以一个数据区是1mb,然后256个数据区被划分为了一组。

对于表空间而言,他的第一组数据区的第一个数据区的前3个数据页,都是固定的,里面存放了一些描述性的数据。比如FSP_HDR这个数据页,他里面就存放了表空间和这一组数据区的一些属性。

IBUF_BITMAP数据页,里面存放的是这一组数据页的所有insert buffer的一些信息。

INODE数据页,这里也是存放了一些特殊的信息

然后这个表空间里的其他各组数据区,每一组数据区的第一个数据区的头两个数据页,都是存放特殊信息的,比如XDES数据页就是用来存放这一组数据区的一些相关属性的,其实就是很多描述这组数据区的东西

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/7344.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ContEA阅读笔记

Facing Changes: Continual Entity Alignment for Growing Knowledge Graphs 面对变化:不断增长的知识图谱的持续实体对齐 Abstract 实体对齐是知识图谱(KG)集成中一项基本且重要的技术。多年来,实体对齐的研究一直基于知识图谱是静态的假设&#xff…

人工智能的发展将如何重塑网络安全

微信搜索关注公众号网络研究观,获取更多信息。 人们很容易认为人工智能 (AI) 真正出现是在 2019 年,当时 OpenAI 推出了 ChatGPT 的前身 GPT-2。 但现实却有些不同。人工智能的基础可以追溯到 1950 年,当时数学家艾伦图灵发表了题为“计算机…

微信小程序如何使用svg矢量图标

微信小程序如何使用自定义SVG矢量图标 在微信小程序中,经常会用到小图标来装饰界面,我们常用的方法就是引用第三方的图标,但会存在收费或者找不到合适的图标,这时候我建议可以自行编写svg图标代码,就可以随心所欲的使…

【一起深度学习——kaggle叶子分类】

kaggle 叶子分类 目的:将叶子进行分类。实现步骤:1、数据处理:2、加载数据3、 定义残差块4、定义Resnet模型。5、定义训练以及评估函数:6、开始训练:7、输出结果: 目的:将叶子进行分类。 实现步…

知识图谱:人工智能的“核心驱动力”

知识图谱:人工智能的“核心驱动力” 一、人工智能与知识图谱二、知识图谱的定义与重要性三、知识图谱工程师的薪资情况四、知识图谱的应用领域六、知识图谱的未来展望七、总结 一、人工智能与知识图谱 人工智能(AI)作为21世纪的前沿技术&…

设备树与/sys/bus/platform/devices与/sys/devices目录关系

设备树与sys/bus/platform/devices sysfs文件系统中/sys/bus/platform/devices下的设备是由设备树生成, 根节点下有compatible的子节点都会在/bus/platform/devices生成节点 总线 I2C、SPI 等控制器会在/bus/platform/devices生成节点 总线 I2C、SPI 节点下的子节点…

牛客网刷题 | BC78 KiKi说祝福语

目前主要分为三个专栏,后续还会添加: 专栏如下: C语言刷题解析 C语言系列文章 我的成长经历 感谢阅读! 初来乍到,如有错误请指出,感谢! 描述 2020年来到了&#…

【Qt】按钮类控件

文章目录 1 :peach:Push Button:peach:2 :peach:Radio Buttion:peach:3 :peach:Check Box:peach:4 :peach:Tool Button:peach: 1 🍑Push Button🍑 使⽤ QPushButton 表⽰⼀个按钮,这也是当前我们最熟悉的⼀个控件了,QPushButton …

SOL链DApp智能合约代币质押挖矿分红系统开发

随着区块链技术的不断发展和普及,越来越多的项目开始探索基于区块链的去中心化应用(DApp)。Solana(SOL)作为一条高性能、低成本的区块链网络,吸引了众多开发者和项目,其中包括了各种类型的DApp&…

Altium Designer——检查原理图库正确性并生成报告

一、方法: 1.打开原理图库: 2.点击菜单栏的报告选项: 3.选择器件规则检查: 根据需求勾选,一般都是全部勾选: 二、问题: 1.缺少封装会导致什么问题: 1.首先: 封装是…

MWeb Pro for Mac:功能强大的Markdown博客编辑器

MWeb Pro for Mac是一款功能强大的Markdown博客编辑器,专为Mac用户设计,提供了一站式的博客写作和发布体验。这款软件不仅支持Markdown语法,还提供了丰富的编辑和排版功能,让用户能够轻松创建出精美的博客内容。 MWeb Pro的即时预…

重庆事业编5月7号开始报名⚠️报名照需审核

24年第二季度重庆事业编招聘 本次招聘实行网上报名。考生应按照招聘岗位要求,诚信、准确填写报考信息,并按网页提示上传电子材料(含电子登记照,jpg格式,20kb以下)。招聘方按照岗位报考要求,对考…

深度学习中的优化算法:选择现有的还是自创?

深度学习中的优化算法 深度学习中的优化算法:选择现有的还是自创?现有优化算法的优势**优点包括**: 开发新的优化算法的考虑**开发新算法的原因**:**开发新算法的风险**: 实用建议结论 深度学习中的优化算法&#xff1…

Mac跑llama.cpp过程中遇到的问题

原repo 在华为手机上安装termux、下载库:顺利在电脑上安装Android NDK:先下载Android Studio,再在里面下载Android SDK 安装Android Studio时,SDK的某些组件总是下载不成功。后来关了梯子、改了hosts,重新安装就成功了…

Ansible---自动化运维工具

一、Ansible概述 1.1 Ansible简介 Ansible是一款自动化运维工具,通过ssh对目标主机进行配置、应用部署、任务执行、编排调度等操作。它简化了复杂的环境管理和自动化任务,提高了工作效率和一致性,同时,Ansible的剧本(playbooks)…

53. 【Android教程】Socket 网络接口

Socket 网络接口 大家在学习计算机网络的时候一定学习过 TCP/IP 协议以及最经典的 OSI 七层结构,简单的回忆一下这 7 层结构: 从下到上依次是: 物理层数据链路层互联层网络层会话层表示层应用层 TCP/IP 协议对这 7 层了做一点精简&#xff…

三岁孩童被家养大型犬咬伤 额部撕脱伤达10公分

近期,一名被家养大型犬咬伤了面部的3岁小朋友,在被家人紧急送来西安国际医学中心医院,通过24小时急诊门诊简单救治后,转至整形外科,由主治医师李世龙为他实施了清创及缝合手术。 “患者额部撕脱伤面积约为10公分&…

Python3中Richdem包遇到问题

Python3中Richdem包遇到问题 文章目录 Python3中Richdem包遇到问题问题一报错解决 问题二报错解决 参考 问题一 报错 RichDEM 是一套数字高程模型 (DEM) 水文分析工具,这次打算用richdem进行地形分析,尝试在conda里面安装richde…

【华为】NAT的分类和实验配置

【华为】NAT的分类和实验配置 NAT产生的技术背景IP地址分类NAT技术原理NAT分类静态NAT动态NATNAPTEasy IP(PAT)NAT Server 配置拓扑静态NAT测试抓包 动态NAT测试抓包 NAPT测试抓包 PAT测试抓包 NAT Server检测抓包 PC1PC2服务器 NAT产生的技术背景 随着…

【管理篇】管理三步曲:团队建设(二)

目录标题 如何着手团队建设提升个人能力1、要提升员工的什么能力2、提升员工个人能力的初衷是什么?3、如何达成上述目标4、应该如何激发员工学习的动力和意愿呢5、关于提升员工的能力,有两个信念特别重要: 提升员工的工作意愿和积极性1、管理…