You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

InnoDB .ibd文件存储疑问:整数存储与溢出页解析

MySQL InnoDB(Dynamic行格式)存储格式疑问解答

测试环境与表信息

MySQL版本:8.0.32
行格式:Dynamic
测试表结构及数据:

CREATE TABLE `demo` (
  `id`   int NOT NULL,
  `age`  int NOT NULL,
  `name` varchar(20000) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=ascii;

INSERT INTO demo(id, age, name) 
VALUES
(1, 10, 'joker'),
(2, 11, 'tom'),
(3, 12, 'jerry'),
(4, 12, 'aaaa...20000 in total...a'),
(5, 16, NULL);

疑问解答

1. 为何MySQL存储有符号整数时未采用补码形式?

InnoDB存储有符号整数时,采用的是偏移量编码而非补码:将有符号整数的取值范围整体偏移,把负数转换为无符号数存储。以int类型为例,其原生取值范围是-231到231-1,存储时会给每个值加上231,原最小值-231会变成0,最大值231-1变成232-1,最终以无符号整数的形式存储。

这种设计的核心是适配B+树的有序性需求,偏移后的无符号数直接按二进制比较大小,结果和逻辑值的排序完全一致,无需额外处理补码符号位的排序逻辑,能简化索引的比较与排序操作,提升整体效率。

2. 当行中所有变长字段均为NULL时,是否不额外存储长度字节?

是的。在Dynamic行格式下:

  • 行记录的NULL标志位(NULL bitmap)会标记哪些字段为NULL;
  • 只有当存在至少一个非NULL的变长字段时,才会在行头部分存储变长字段长度列表(每个非NULL变长字段对应1或2个字节的长度值,根据实际长度大小选择);
  • 如果所有变长字段都为NULL,不会额外存储长度字节,因为没有需要记录长度的非NULL变长字段。

比如测试数据中的第5行(id=5, age=16, name=NULL),无任何非NULL的变长字段,因此行记录中不会有变长长度字节的存储开销。

3. 变长字段过长导致页溢出时,额外字节代表什么含义?

在Dynamic行格式下,当变长字段的长度超过页大小的1/4(默认页大小为16KB,即超过4KB)时,会触发页溢出:

  • 原行记录中仅存储该字段的20字节指针,这个指针指向实际存储字段内容的溢出页(或溢出段);
  • 这20字节的结构为:表空间ID(4字节) + 溢出页号(4字节) + 页内偏移量(4字节) + 字段总长度(8字节),通过这套指针可以准确定位到溢出内容的位置。

和Compact行格式不同,Dynamic格式不会在原行中存储字段的前缀内容,仅存储完整指针,以此最大程度节省原数据页的空间,提升页内存储密度。


内容的提问来源于stack exchange,提问作者spin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 17:17:25