当前位置: 首页 > news >正文

MySQL:一行记录如何

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)

相关文章:

MySQL:一行记录如何

1、表空间文件结构 表空间由段「segment」、区「extent」、页「page」、行「row」组成&#xff0c;InnoDB存储引擎的逻辑存储结构大致如下图&#xff1a; 行 数据库表中的记录都是按「行」进行存放的&#xff0c;每行记录根据不同的行格式&#xff0c;有不同的存储结构。 页…...

‘grafana.ini‘ is read only ‘defaults.ini‘ is read only

docker安装grafana 关闭匿名登录情况下的免密登录遇到问题 grafana.ini is read only defaults.ini is read only 参考回答&#xff08;Grafana.ini giving me the creeps - #2 by bartweemaels - Configuration - Grafana Labs Community Forums&#xff09; 正确启动脚本 …...

博途PLC 面向对象系列之“输送带控制功能块“(SCL代码)

这篇是面向对象系列之"输送带功能块"的封装,面向对象是系列文章,相关链接如下: 1、面向对象系列之找"对象" https://rxxw-control.blog.csdn.net/article/details/136150027https://rxxw-control.blog.csdn.net/article/details/1361500272、面向对象…...

2024-02学习笔记

1.当我们向Set集合中添加一个已经存在的元素时 当我们向Set集合中添加一个已经存在的元素时&#xff0c;Set集合会如何处理呢&#xff1f;实际上&#xff0c;Set集合不会将重复的元素添加到集合中。当我们向Set集合中添加一个元素时&#xff0c;Set集合会首先判断该元素是否已…...

最新消息:英特尔宣布成立全新独立运营的FPGA公司——Altera

今天&#xff0c;英特尔宣布成立全新独立运营的FPGA公司——Altera&#xff08;2015年6月Intel以 167 亿美元的价格&#xff0c;收购FPGA厂商Altera&#xff09;。首席执行官Sandra Rivera和首席运营官Shannon Poulin分享展示其在超过550亿美元的市场中保持领先性的战略规划&am…...

RC正弦波振荡电路

RC正弦波振荡电路 RC正弦波振荡电路又称文氏电桥振荡电路&#xff0c;可以设计频率为f1/2πRC的正弦波发生器。 RC正弦波振荡电路设计&#xff1a;50Hz,振幅为3.47V 电路分析&#xff1a; 1.起振条件取决于R1, R4&#xff0c;R2与1N4148并联电阻&#xff08;下面简称Rf&#…...

【Git学习笔记】提交PR

step1 克隆一个仓库 git clone .....step2 创建一个分支 (Creating a branch) # 创建并切换到本地新分支&#xff0c;分支的命名尽量简洁&#xff0c;并与解决的问题相关 git checkout -b delete-unused-linkstep3 做出修改 (Make changes) step4 提交修改 # 保存本地修…...

线程池的相关参数

在Java中线程池是一种池化技术&#xff0c;用于管理和复用线程&#xff0c;提高线程的利用率和性能。下面是一些常见的线程池的参数及其解释&#xff1a; 一&#xff1a;线程池的七大参数 public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTim…...

图书推荐||Word文稿之美

让你的文档从平凡到出众&#xff01; 本书内容 《Word文稿之美》是一本全面介绍Word排版技巧和应用的实用指南。从初步认识数字排版到高效利用模板、图文配置和表格与图表的排版技巧&#xff0c;再到快速修正错误和保护文件&#xff0c;全面系统地讲解数字排版的技术和能力&…...

前端导出word文件的多种方式、前端导出excel文件

文章目录 纯前借助word模板端导出word文件 &#xff08;推荐&#xff09;使用模板导出 前端通过模板字符串导出word文件前端导出 excel文件&#xff0c;node-xlsx导出文件&#xff0c;行列合并 纯前借助word模板端导出word文件 &#xff08;推荐&#xff09; 先看效果&#xf…...

Linux和Windows操作系统在腾讯云幻兽帕鲁服务器上的内存占用情况如何?

Linux和Windows操作系统在腾讯云幻兽帕鲁服务器上的内存占用情况如何&#xff1f; 对于Linux操作系统&#xff0c;有用户分享了个人最佳实践来解决内存问题&#xff0c;包括使用Linux脚本让服务器每天重启一次&#xff0c;以及建议在不需要时尽量减少虚拟内存的使用。此外&…...

腾讯云4核8G的云服务器性能水平?使用场景说明

腾讯云4核8G服务器适合做什么&#xff1f;搭建网站博客、企业官网、小程序、小游戏后端服务器、电商应用、云盘和图床等均可以&#xff0c;腾讯云4核8G服务器可以选择轻量应用服务器4核8G12M或云服务器CVM&#xff0c;轻量服务器和标准型CVM服务器性能是差不多的&#xff0c;轻…...

1_SQL

文章目录 前端复习SQL数据库的分类关系型数据库非关系型数据库&#xff08;NoSQL&#xff09; 数据库的构成软件架构MySQL内部数据组织方式 SQL语言登录数据库数据库操作查看库创建库删除库修改库 数据库中表的操作选择数据库创建表删除表查看表修改表 数据库中数据的操作添加数…...

PoC免写攻略

在网络安全领域&#xff0c;PoC&#xff08;Proof of Concept&#xff09;起着重要的作用&#xff0c;并且在安全研究、漏洞发现和漏洞利用等方面具有重要的地位。攻击方视角下&#xff0c;常常需要围绕 PoC 做的大量的工作。常常需要从手动测试开始编写 PoC&#xff0c;再到实…...

c1-周考2

c1-第二周 9月-技能1.一个岛上有两种神奇动物&#xff0c;其中神奇鸟类2个头3只脚&#xff0c;神奇兽类3个头8只脚。游客在浓雾中看到一群动物&#xff0c;共看到35个头和110只脚&#xff0c;求可能的鸟类和兽类的只数2.构建一个长度为5的数组&#xff0c;并且实现下列要求3.构…...

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接…...

markdown的使用(Typora)

文章目录 markdown的使用(Typora)一.标题二.段落格式2.1 换行2.2 分割线2.3 字体2.4 上下标2.5 脚注2.6 改变字体颜色 三.列表3.1 无序列表3.2 有序列表3.3 列表嵌套3.4 任务列表 四.区块五.代码显示5.1 行内代码5.2 代码块 六.链接七.图片八.表格九.表情符号大纲十、流程图10.…...

【python】json转成成yaml中文编码异常显示成:\u5317\u4EAC\u8DEF123\u53F7

姊妹篇&#xff1a;【python】json转成成yaml json数据 {"name": "张三","age": 30,"isMarried": false,"children": [{"name": "小王","age": 5},{"name": "小李",&qu…...

Python 实现Excel自动化办公(中)

在上一篇文章的基础上进行一些特殊的处理&#xff0c;这里的特殊处理主要是涉及到了日期格式数据的处理&#xff08;上一篇文章大家估计也看到了日期数据的处理是不对的&#xff09;以及常用的聚合数据统计处理&#xff0c;可以有效的实现你的常用统计要求。代码如下&#xff1…...

MCTS代码

这段代码的背景是玩一个游戏。游戏的参数有NUM_TURNS&#xff0c;在第i回合&#xff0c;你可以从一个整数[-2,2,3&#xff0c;-3]*&#xff08;NUM_TURNS1-i&#xff09;中进行选择。例如&#xff0c;在一个4回合的游戏中&#xff0c;在第1回合&#xff0c;你可以从[-8,8,12&am…...

Vim 调用外部命令学习笔记

Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

手游刚开服就被攻击怎么办?如何防御DDoS?

开服初期是手游最脆弱的阶段&#xff0c;极易成为DDoS攻击的目标。一旦遭遇攻击&#xff0c;可能导致服务器瘫痪、玩家流失&#xff0c;甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案&#xff0c;帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

【kafka】Golang实现分布式Masscan任务调度系统

要求&#xff1a; 输出两个程序&#xff0c;一个命令行程序&#xff08;命令行参数用flag&#xff09;和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽&#xff0c;然后将消息推送到kafka里面。 服务端程序&#xff1a; 从kafka消费者接收…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别

一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

React Native 导航系统实战(React Navigation)

导航系统实战&#xff08;React Navigation&#xff09; React Navigation 是 React Native 应用中最常用的导航库之一&#xff0c;它提供了多种导航模式&#xff0c;如堆栈导航&#xff08;Stack Navigator&#xff09;、标签导航&#xff08;Tab Navigator&#xff09;和抽屉…...

Xshell远程连接Kali(默认 | 私钥)Note版

前言:xshell远程连接&#xff0c;私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

蓝桥杯 2024 15届国赛 A组 儿童节快乐

P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡&#xff0c;轻快的音乐在耳边持续回荡&#xff0c;小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下&#xff0c;六一来了。 今天是六一儿童节&#xff0c;小蓝老师为了让大家在节…...

Linux --进程控制

本文从以下五个方面来初步认识进程控制&#xff1a; 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程&#xff0c;创建出来的进程就是子进程&#xff0c;原来的进程为父进程。…...

Python ROS2【机器人中间件框架】 简介

销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...

Linux离线(zip方式)安装docker

目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1&#xff1a;修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本&#xff1a;CentOS 7 64位 内核版本&#xff1a;3.10.0 相关命令&#xff1a; uname -rcat /etc/os-rele…...