MySQL varchar 的最大长度

备注:全文示例皆在 8.0.17 版本下进行。


在MySQL官方定义中,常用的 COMPACTDYNAMIC行模式下,varchar 的最大长度并不是固定数值,取决于以下限制:

  1. 行长度限制;
  2. 编码长度限制;
  3. 存储限制。

行长度限制

MySQL 要求一行的定义长度不能超过 65535 字节(约 64 KB)。若定义长度超过这个值,则提示:

1118 - Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs

编码长度限制

每个字符的实际占据的空间与字符所使用的字符集相关。下表列举的一些例子:

字符集 每个字符占用存储空间(单位:字节)
latin1 1
GBK 2
UTF8 3
UTF8MB4 4

存储限制

根据限制 1,每行最多能存储 65535 字节的数据,这包括:

  1. 所有字段的长度;
  2. 每个变长字段的长度,当存储的长度小于 255 字节时,需要 1 字节记录,大于 255 字节时,需要 2 字节;
  3. NULL 标识位的累计长度。

其中,NULL 标记位用于表示某个字段是否允许为 NULL。每个字段使用 1 个 bit 位来表示。每 8 个标记组成一个字段。若一行中有 N 个字段,则一行中用于 NULL 标记位所消耗的空间计算公式为:

或者这样表示:⌈ N / 8 ⌉ (向上取整)。

长度计算

最大长度(字符数) = (行存储最大字节数 - NULL标识列占用字节数 - 长度标识字节数) / 字符集单字符最大字节数。有余数时向下取整。

长度标识位表示的是字节数。大于 255 后使用两字节,是因为按照可能的数据大小,分为 0~255(2^8)、256~65535(2^16),分别对应 1 字节和 2 字节。

根据字段声明的字符长度,计算可能的字节数,再决定长度标志的字节数。如 VARCHAR(100),字符集为 UTF8,可能的字节数为 300,则长度标识为 2 字节。

长度标志位只是存储开销,不影响长度约束。长度约束的是数据的字符数,允许的最大字符数与字符集有关。

如列指定字符集为 UTF8、每个字符最大可占用 3 个字节,行最大长度为 65535 字节,那么该列可设置的最大列大小为65535 ÷ 3 ≈ 21844(向下取整)。

同理如果是 UTF8MB4,单字符最大占 4 个字节,可设置最大列大小为 65535 ÷ 4 ≈ 16383(向下取整)。

Built with Hugo
Theme Stack designed by Jimmy