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

为什么MySQL的CHAR datatype无前置长度字节?引擎如何识别其长度?

MySQL 引擎获取CHAR类型长度的实现机制

CHAR类型不需要在行存储中预留长度字节,核心原因是它的长度信息从表结构定义阶段就被持久化存储了,根本不需要跟着每行数据重复存储。

核心实现逻辑

  • 建表时声明的CHAR(M),会把M(字段允许的最大字符长度)直接写入数据库的数据字典(系统表)中。数据库打开表执行查询时,会把所有字段的定义、在数据行中的偏移位置、固定占用空间大小全部加载到内存,读取行数据之前就已经明确知道每个CHAR字段要读取的字节长度。
  • CHAR是定长类型,存储时会为每个值固定分配「M * 字符集单字符最大字节数」的空间:比如utf8mb4字符集下CHAR(10)固定预留40字节空间,存储的字符串长度不足M时,会在尾部用空格填充到固定长度;读取时按预计算的偏移量直接切取对应长度的字节,再把尾部填充的空格剔除(除非开启PAD_CHAR_TO_FULL_LENGTH模式),就能拿到实际存储的字符串内容,全程不需要额外的长度标识。

和VARCHAR的设计差异

VARCHAR作为变长类型,不会为每个值按最大声明长度预留空间,不然会造成极大的存储浪费:比如VARCHAR(255)存1个字符的短字符串,要是也按255字节预留空间,绝大多数空间都是无效空值。
正因如此,VARCHAR才需要在每个值的前面加1-2个字节存储实际内容长度:

  • 当声明的最大长度不超过255字节时,用1个字节存长度(1字节无符号数最大可表示255,足够覆盖长度范围)
  • 当声明的最大长度超过255字节时,用2个字节存长度(2字节无符号数最大可表示65535,正好匹配InnoDB单行最大65535字节的存储限制)
    引擎读取VARCHAR字段时,会先读前置的长度字节拿到实际内容长度,再往后读取对应长度的字节即可,不需要按固定偏移切分。

常见误区:很多人以为CHAR存的内容不带尾部空格就没法识别长度,实际上填充空格是CHAR定长存储规则的一部分,尾部补多少空格、读取时删多少空格,规则都写在字段元数据里,不需要在行里额外标记。

举个直观的存储对比,同样存储字符串"test":

  1. 字段定义为CHAR(6) CHARACTER SET utf8mb4:元数据标记该字段固定占24字节,行内实际存储为"test "(补2个空格凑够6字符),引擎直接从行对应偏移位置切24字节,剔除尾部2个填充空格就得到有效内容。
  2. 字段定义为VARCHAR(6) CHARACTER SET utf8mb4:行内先存1个长度字节0x04(标记有效内容占4字节),后面跟着存"test",总共占5字节,引擎先读1字节拿到长度4,再往后读4字节就是有效内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 02:01:24