MySQL InnoDB 变长列实际使用的字节数到底用几个 Bytes 表示?

行大小的限制

max row size

MariaDB enforces a 65,535 byte limit on a table's maximum row size.
The total size of a table's BLOB and TEXT columns do not count towards this limit.
Only the pointers for a table’s BLOB and TEXT columns count towards this limit.
MariaDB enforces this limit for all storage engines, so this limit also applies to InnoDB tables.
Therefore, this limit is the absolute maximum row size for an InnoDB table.
MariaDB 对表的最大行大小执行 65535 字节的限制。
表的 BLOB 和 TEXT 列的总大小没有此限制。
只有表的 BLOB 和 TEXT 列的指针才计入此限制。
MariaDB 对所有存储引擎都强制执行这个限制,因此这个限制也适用于 InnoDB 表。
因此,这个限制是 InnoDB 表的绝对最大的行大小。

变长列长度

由上可知就算一行只有一个变长列,那么最多需要 2Bytes(2^16 - 1 = 65535) 表示变长列的长度。

到底用 1Byte or 2Bytes 表示变长列长度?

以 varchar(M) 为例。来理解。

列所采用的字符集的 maxlen

maxlen和列使用的字符集有关系。就是使用某种字符集来表示一个字符,最多可以使用的字节数。这里 maxlen 记作 W

mysql> show charset; # 节选了部分
+----------+---------------------------------+---------------------+--------+
| Charset  | Description                     | Default collation   | Maxlen |
+----------+---------------------------------+---------------------+--------+
| latin7   | ISO 8859-13 Baltic              | latin7_general_ci   |      1 |
| utf8mb4  | UTF-8 Unicode                   | utf8mb4_general_ci  |      4 |
| cp1251   | Windows Cyrillic                | cp1251_general_ci   |      1 |
| utf16    | UTF-16 Unicode                  | utf16_general_ci    |      4 |
| utf16le  | UTF-16LE Unicode                | utf16le_general_ci  |      4 |
| utf32    | UTF-32 Unicode                  | utf32_general_ci    |      4 |
| binary   | Binary pseudo charset           | binary              |      1 |
| geostd8  | GEOSTD8 Georgian                | geostd8_general_ci  |      1 |
| cp932    | SJIS for Windows Japanese       | cp932_japanese_ci   |      2 |
| eucjpms  | UJIS for Windows Japanese       | eucjpms_japanese_ci |      3 |
| gb18030  | China National Standard GB18030 | gb18030_chinese_ci  |      4 |
+----------+---------------------------------+---------------------+--------+
41 rows in set (0.00 sec)

变长列 varchar(M) 存储字符的最大数

varchar(M) 可以存储字符的最大数记作 M

varchar(M) 存储实际所用的字节数

varchar(M) 存储实际所用的字节数记作 L
理论上 varchar(M) 可以使用的最大字节数 M * W

分类讨论

可变字段理论上可使用最大字节数 W * M <= 255

实际上使用的字节数也 <= 255。此时 1Byte 来表示 varchar(M) 实际使用的字节数 L,足矣。情况(1)

可变字段理论上可使用最大字节数 W * M > 255
情况1: 实际使用的字节数 L <= 127

1Byte 存储足矣。情况 (2)

情况2:实际使用的字节数 L > 127

2Bytes 存储。

可变字段理论上可使用最大字节数 W * M > 255。情况1 和 情况2 如何区分?

在这里插入图片描述
根据存储实际长度的那个字节的最高位判断。

  1. 最高位是 0: 情况 1,存储使用的字节数,只用 1Byte 存储。
  2. 最高位是 1: 情况 2,存储使用的字节数,只用 2Byte 存储。
总结

如果该可变字段允许存储的最大字节数(M×W)超过 255 字节并且真实存储的字节数(L)超过 127 字节,则使用 2 个字节,否则使用 1 个字节。

这么麻烦干啥呢?

这么折腾干啥呢?为啥不都用 2Bytes 表示呢?为了节省 1Byte 的存储空间。

References

  1. innodb-table-maximum-row-size
  2. 行格式
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值