MySQL:一行记录如何

news2024/11/16 13:27:41

1、表空间文件结构

表空间由段「segment」、区「extent」、页「page」、行「row」组成,InnoDB存储引擎的逻辑存储结构大致如下图:

数据库表中的记录都是按「行」进行存放的,每行记录根据不同的行格式,有不同的存储结构。

记录是按照行来存储的,但是数据库的读取并不以「行」为单位,否则一次读取(也就是一次 I/O 操作)只能处理一行数据,效率会非常低。

因此,InnoDB 的数据是按「页」为单位来读写的,也就是说,当需要读一条记录的时候,并不是将这个行记录从磁盘读出来,而是以页为单位,将其整体读入内存。

默认每个页的大小为 16KB,也就是最多能保证 16KB 的连续存储空间。

页是 InnoDB 存储引擎磁盘管理的最小单元,意味着数据库每次读写都是以 16KB 为单位的,一次最少从磁盘中读取 16KB 的内容到内存中,一次最少把内存中的 16KB 内容刷新到磁盘中。

B+ 树中每一层都是通过双向链表连接起来的,如果是以页为单位来分配存储空间,那么链表中相邻的两个页之间的物理位置并不是连续的,可能离得非常远,那么磁盘查询时就会有大量的随机 I/O,随机 I/O 是非常慢的。

怎么解决呢?

在表中数据量大的时候,为某个索引分配空间的时候就不再按照页为单位分配了,而是按照「区」为单位分配。每个区的大小为 1MB,对于 16KB 的页来说,连续的 64 个页会被划为一个区,这样就使得链表中相邻的页的物理位置也相邻,就能使用顺序 I/O 了。

表空间是由各个段组成的,段是由多个区组成的。段一般分为「数据段」、「索引段」和「回滚段」等。

  • 索引段:存放 B + 树的非叶子节点的区的集合。
  • 数据段:存放 B + 树的叶子节点的区的集合。
  • 回滚段:存放的是回滚数据的区的集合,MVCC 利用了回滚段实现了多版本查询数据。

2、InnoDB 行格式

有下面 4 种行格式:

  • Redundant:MySQL 5.0 版本之前用的行格式,不紧凑。
  • Compact:MySQL 5.1 版本之后,行格式默认设置成 Compact。一种紧凑的行格式,可以让一页存储更多行记录。
  • DynamicCompressed:从 MySQL5.7 版本之后,默认使用 Dynamic 行格式。 两个都是紧凑的行格式,它们的行格式都和 Compact 差不多,都是基于 Compact 改进一点东西。

COMPACT 行格式

记录的额外信息
1. 变长字段长度列表

varchar(n)char(n) 的区别:char 是定长的,varchar 是变长的,变长字段实际存储的数据的长度(大小)不固定的。

在存储数据的时候,要把数据占用的大小存起来,存到「变长字段长度列表」里面,读取数据的时候才能根据这个「变长字段长度列表」去读取对应长度的数据。其他 TEXT、BLOB 等变长字段也是这么实现的。

【示例】创建下面表进行演示:

假设有下面三条记录:

image.png

第一条记录「只看变长字段」:

  • name字段值为 a,占 1 字节。
  • phone 字段值为 123,占 3 字节。

这些变长字段的真实数据占用的字节数会按照列的顺序 逆序存放,所以「变长字段长度列表」里的内容是「 03 01」,而不是 「01 03」。

同理,第二条记录:

第三条记录phone 列的值是 NULL,NULL 是不会存放在行格式中记录的真实数据部分里的,所以「变长字段长度列表」里不需要保存值为 NULL 的变长字段的长度。

【为什么「变长字段长度列表」的信息要按照逆序存放】

因为「记录头信息」中指向下一个记录的指针,指向的是下一条记录的「记录头信息」和「真实数据」之间的位置,这样的好处是向左读就是记录头信息,向右读就是真实数据,比较方便。

「变长字段长度列表」中的信息之所以要逆序存放,是因为这样可以使得位置靠前的记录的真实数据和数据对应的字段长度信息可以同时在一个 CPU Cache Line 中,这样就可以提高 CPU Cache 的命中率

当数据表没有变长字段的时候,比如全部都是 int 类型的字段,这时候表里的行格式就不会有「变长字段长度列表」了,因为没必要,不如去掉以节省空间。

所以「变长字段长度列表」只出现在数据表有变长字段的时候。

2. NULL 值列表

表中的某些列可能会存储 NULL 值,如果把这些 NULL 值都放到记录的真实数据中会比较浪费空间,所以 Compact 行格式把这些值为 NULL 的列存储到 NULL 值列表中。

如果存在允许 NULL 值的列,则每个列对应一个二进制位(bit),二进制位按照列的顺序逆序排列。

  • 二进制位的值为1时,代表该列的值为 NULL。
  • 二进制位的值为0时,代表该列的值不为 NULL。

另外,NULL 值列表必须用整数个字节的位表示(1字节8位),如果使用的二进制位个数不足整数个字节,则在字节的高位补 0

当一条记录有 9 个字段值都是 NULL,那么就会创建 2 字节空间的「NULL 值列表」,以此类推。

当数据表的字段都定义成 NOT NULL 的时候,这时候表里的行格式就不会有 NULL 值列表了

所以在设计数据库表的时候,通常都是建议将字段设置为 NOT NULL,这样可以至少节省 1 字节的空间(NULL 值列表至少占用 1 字节空间)。


【举例】以上面表举例:

第一条记录:

但是 InnoDB 是用整数字节的二进制位来表示 NULL 值列表的,现在不足 8 位,所以要在高位补 0,最终用二进制来表示:

第二条记录:

第三条记录 phone 列 和 age 列是 NULL 值,所以,对于第三条数据,NULL 值列表用十六进制表示是 0x06。

 NULL 值列表填充完毕后,行格式为下面这样:

3. 记录头信息

列举比较重要的几个:

  • delete_mask:标识此条数据是否被删除。执行 detele 删除记录的时候,并不会真正的删除记录,只是将这个记录的 「delete_mask」标记为 1
  • next_record:下一条记录的位置。记录与记录之间是通过链表组织的,指向的是下一条记录的「记录头信息」和「真实数据」之间的位置,这样的好处是向左读就是记录头信息,向右读就是真实数据,比较方便。
  • record_type:表示当前记录的类型,0 表示普通记录,1 表示 B+ 树非叶子节点记录,2 表示最小记录,3 表示最大记录。
记录的真实数据

记录真实数据部分除了自定义的字段,还有三个隐藏字段,分别为:row_idtrx_idroll_pointer

  • row_id:建表的时候指定了主键或者唯一约束列,那么就没有 row_id 隐藏字段了。如果既没有指定主键,又没有唯一约束,那么 InnoDB 就会为记录添加 row_id 隐藏字段。row_id 不是必需的,占用 6 个字节。

  • trx_id:事务id,表示这个数据是由哪个事务生成的。 trx_id 是必需的,占用 6 个字节。

  • roll_pointer:这条记录上一个版本的指针。roll_pointer 是必需的,占用 7 个字节。

MVCC 机制就跟 trx_id 和 roll_pointer 的作用有关。

varchar(n) 中的 n 最大取值

MySQL 规定除了 TEXT、BLOBs 这种大对象类型之外,其他所有的列(不包括隐藏列和记录头信息)占用的字节长度「加起来」不能超过 65535 个字节

varchar(n) 字段类型的 n 代表的是最多存储的字符数量,并不是字节大小。

要算 varchar(n) 最大能允许存储的字节数,还要看数据库表的字符集,因为字符集代表着:1个字符要占用多少字节,比如 ascii 字符集, 1 个字符占用 1 字节,那么 varchar(100) 意味着最大能允许存储 100 字节的数据。

【单字段情况】

在算 varchar(n) 中 n 最大值时,需要减去 「变长字段长度列表」和 「NULL 值列表」所占用的字节数的。

【多字段情况】

如果有多个字段的话,要保证「所有字段的长度 + 变长字段字节数列表所占用的字节数 + NULL值列表所占用的字节数」 <= 65535。

行溢出后,如何存储数据

如果一个数据页存不了一条记录,InnoDB 存储引擎会自动将溢出的数据存放到「溢出页」中。

在记录的真实数据处只会保存该列的一部分数据,而把剩余的数据放在「溢出页」中,然后「真实数据」处用 20 字节存储指向溢出页的地址,从而可以找到剩余数据所在的页。

 转载:MySQL 一行记录是怎么存储的? | 小林coding (xiaolincoding.com)

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

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

相关文章

跨域引起的两个接口的session_id不是同一个

来源场景&#xff1a; RequestMapping(“/captcha”)接口设置了SESSION_KEY&#xff0c;也能获取到&#xff0c;但是到了PostMapping(“/login”)接口就是空的&#xff0c;由于跨域导致的两个session_id不是同一个 /*** 系统用户 前端控制器*/ Controller CrossOrigin(origins…

vue项目电商

这个项目功能有首页&#xff0c;分类&#xff0c;商品详情&#xff0c;购物车&#xff0c;用户注册、登录等等的实现&#xff0c;并且可以在手机上进行展示。 git仓库地址&#xff1a;https://gitee.com/BisShen/project.git

分类问题经典算法 | 二分类问题 | Logistic回归:梯度下降

目录 一. 损失函数1. 交叉熵损失函数2. 梯度下降 一. 损失函数 Logistic回归算法公式推导篇中&#xff0c;我们通过对似然函数求对数&#xff0c;得到 l ( θ ) l(\theta ) l(θ)&#xff1a; l ( θ ) l n [ L ( θ ) ] ∑ i 1 M { y ( i ) l n [ h θ ( x ( i ) ) ] ( …

【Python笔记-FastAPI】后台任务+WebSocket监控进度

目录 一、代码示例 二、执行说明 (一) 调用任务执行接口 (二) 监控任务进度 实现功能&#xff1a; 注册后台任务&#xff08;如&#xff1a;邮件发送、文件处理等异步场景&#xff0c;不影响接口返回&#xff09;监控后台任务执行进度&#xff08;进度条功能&#xff09;支…

2024最新算法:河马优化算法(Hippopotamus optimization algorithm,HO)求解23个基准函数,提供MATLAB代码

一、河马优化算法 河马优化算法&#xff08;Hippopotamus optimization algorithm&#xff0c;HO&#xff09;由Amiri等人于2024年提出&#xff0c;该算法模拟了河马在河流或池塘中的位置更新、针对捕食者的防御策略以及规避方法。河马优化算法的灵感来自河马生活中观察到的三…

在Windows系统上安装Docker和SteamCMD容器的详细指南有哪些?

在Windows系统上安装Docker和SteamCMD容器的详细指南有哪些&#xff1f; 安装Docker&#xff1a; 首先&#xff0c;需要在Windows操作系统上激活WSL2功能。这是因为Docker作为一个容器工具&#xff0c;依赖于已存在并运行的Linux内核环境。可以通过使用winget来安装Docker。具体…

[技巧]Arcgis之图斑四至范围批量计算

ArcGIS图层&#xff08;点、线、面三类图形&#xff09;四至范围计算 例外一篇介绍&#xff1a;[技巧]Arcgis之图斑四至点批量计算 说明&#xff1a;如下图画出来的框&#xff08;范围标记不是很准&#xff09; &#xff0c;图斑的x最大和x最小&#xff0c;y最大&#xff0c;…

2024年全国乙卷高考理科数学备考:十年选择题真题和解析

今天距离2024年高考还有三个多月的时间&#xff0c;今天我们来看一下2014~2023年全国乙卷高考理科数学的选择题&#xff0c;从过去十年的真题中随机抽取5道题&#xff0c;并且提供解析。后附六分成长独家制作的在线练习集&#xff0c;科学、高效地反复刷这些真题&#xff0c;吃…

聊聊 HTTP 性能优化

作为用户的我们在 "上网冲浪" 的时候总是希望快一点&#xff0c;尤其是抢演唱会门票的时候&#xff0c;但是现实并非如此&#xff0c;有时候我们会遇到页面加载缓慢、响应延迟的情况。 而 HTTP 协议作为互联网世界的基础&#xff0c;从网站打开速度到移动应用的响应…

Maven-私服(黑马学习笔记)

前面我们在讲解多模块开发的时候&#xff0c;我们讲到我们所拆分的模块是可以在同一个公司各个项目组之间进行资源共享的。这个模块的资源共享&#xff0c;就需要通过我们接下来所讲解的Maven的私服来实现。 首先我们先介绍一下什么是私服&#xff0c;以及它的作用是什么。再来…

教育培训课程课件学校报名营销学生作业习题小程序开发

学校教育培训课程课件报名营销学生作业习题小程序全面开发 核心功能 校区课程&#xff1a;一键报名&#xff0c;便捷缴费 砍价助力&#xff1a;邀请好友&#xff0c;共享低价优惠 视频课程&#xff1a;倍速播放&#xff0c;学习更高效 商城管理&#xff1a;商品、订单一目…

express+mysql+vue,从零搭建一个商城管理系统7--文件上传,大文件分片上传

提示&#xff1a;学习express&#xff0c;搭建管理系统 文章目录 前言一、安装multer&#xff0c;fs-extra二、新建config/upload.js三、新建routes/upload.js四、修改routes下的index.js五、修改index.js六、新建上传文件test.html七、开启jwt验证token&#xff0c;通过login接…

UI自动化-(web端下拉选择框弹出框滚动条操作-实操入门)

1、下拉选择框操作 在 UI 自动化中,操作下拉选择框可以通过以下步骤进行: 定位下拉选择框元素:通过适当的元素定位方法,找到下拉选择框的元素。打开下拉框:例如通过点击(.click)来操作下拉框元素打开下拉框。选择选项:可以通过以下几种方式选择下拉框中的选项:根据索…

【01】openEuler 源码安装 PostgreSQL

openEuler 源码安装 PostgreSQL 部署环境说明Shell 前端软件包管理器基础概念YUM 简介DNF 简介 源码安装 PostgreSQL环境变量&#xff08;env&#xff09;设置临时环境变量设置永久环境变量设置 初始化数据库&#xff08;initdb&#xff09; 数据库基本操作数据库基本配置&…

【漏洞复现】某厂商明御WEB应用防火墙任意用户登录漏洞

Nx01 产品简介 安恒明御WEB应用防火墙&#xff08;简称WAF&#xff09;是杭州安恒信息技术股份有限公司自主研发的一款专业应用安全防护产品&#xff0c;专注于为网站、APP等Web业务系统提供安全防护。 Nx02 漏洞描述 安恒明御WEB应用防火墙report.php文件存在硬编码设置的Con…

当代人吃瓜成习惯!后续来了!人生进阶5个方法——早读(逆天打工人爬取热门微信文章解读)

让瓜再熟一点 引言python代码第一篇 春秋航空 开年首场机票限时抢&#xff01;春日畅飞&#xff0c;多重好礼第二篇 人民日报 “我该给十年前的支教老师打电话吗&#xff1f;”后续来了&#xff01;第三篇 人民日报 【夜读】想要人生进阶&#xff0c;试试这五种方法第四篇&…

python自动化之项目架构搭建与思路讲解(第二天)

1.自动化测试的概念 自动化测试是指使用自动化工具和脚本来执行测试任务,以验证软件或系统的正确性和稳定性。它可以提高测试的效率和准确性,并节约时间和成本。 2.自动化脚本编写的思路 xmind文档如有需要,可在资源里自行下载 3.项目代码工程创建 lib :基本代码库包 …

【Leetcode】2369. 检查数组是否存在有效划分

文章目录 题目思路代码结果 题目 题目链接 给你一个下标从 0 开始的整数数组 nums &#xff0c;你必须将数组划分为一个或多个 连续 子数组。 如果获得的这些子数组中每个都能满足下述条件 之一 &#xff0c;则可以称其为数组的一种 有效 划分&#xff1a; 子数组 恰 由 2 个…

Thinkphp框架漏洞--->5.0.23 RCE

1.Thinkphp ThinkPHP是一个免费开源的&#xff0c;快速、简单的面向对象的轻量级PHP开发框架&#xff0c;是为了敏捷WEB应用开发和简化 企业应用开发而诞生的。 2.漏洞原理及成因 该漏洞出现的原因在于 ThinkPHP5框架底层对控制器名过滤不严 &#xff0c;从而让攻击者可以通过…

抖音小店无货源怎么做起来?正确玩法是什么?做店步骤都在这里了

大家好&#xff0c;我是电商花花。 新的一年肯定又会有不少创业者疑问2024年抖音小店还能继续做吗&#xff1f;怎么做才能赚到钱&#xff1f; 尤其是现在做无货源模式&#xff0c;还会被判罚吗&#xff1f; 我认为2024年的抖音小店不管是有货源还是无货源都是可以做的&#…