MySQL的varchar长度能大于4000吗?

程序员阿牛
2021-07-01 / 0 评论 / 1,078 阅读
温馨提示:
本文最后更新于2021-07-01,若内容或图片失效,请留言反馈。

前言

相信这个问题你在度娘上能搜出来结果,但是大多数只是一个简单的答案,其他就什么也没有了,或者说拷贝来拷贝去,千篇一律都是一样或者类似的。

正文

我们先看下官方给出的答案:

Values in VARCHAR columns are variable-length strings. The length can be specified as a value from 0 to 65,535. The effective maximum length of a VARCHAR is subject to the maximum row size (65,535 bytes, which is shared among all columns) and the character set used.

翻译成中文就是:

VARCHAR列中的 值是可变长度的字符串。长度可以指定为 0 到 65,535 之间的值。VARCHAR的有效最大长度受最大行大小(65,535 字节,在所有列之间共享)和使用的字符集的约束。

根据官方文档进一步翻译就是,一个VARCHAR的最大长度最大是65535,但是65535是一张表的所有列共享的,不是每个字段都能是65535,另外VARCHAR的长度还受字符集的影响。为了更形象的了解上面的解释,我们接下来做几个实验。

字符集为latin1(1个字段)

image.png

不是一行数据能存65535个字节吗,这里怎么会报错呢?如果你看过我上篇文章,你一定还记得,这里给大家复习一下

Mysql行格式大概(为什么是大概,因为大同小异)是这样的
image.png
因为每一行是有额外的信息啊,因为varchar(M)是变长的,在latin1编码下,M>255是,需要2个字节来表示所存储的真实数据,另外因为c1列是可空的,所以又需要1个字节来表示各列是否为空值,因此65535-2-1=65532。

这时候你或许还有疑问,你上篇文章不是说记录头还会占5个字节的吗,虽然是行格式里面有记录头,记录头主要作用是负责管理记录间的管理关系,不属于数据本身,但是变长属性长度和是否NULL值都是密切相关的。

根据上面的分析,我们在做一下实验,来验证我们说的对不对
1、字段可空时
image.png

image.png

2、字段不可空时
image.png

字符集为latin1(2个字段)

按照上面的分析,继续做2个实验

1、字段可空
image.png
字段长度字段数量+存储字段长度所需要的字节字段数量+存储NULL值列表需要字节=行数据长度
即:327652+22+1=65535
所以能执行成功。如果定义字段长度大于32766,会不会执行成功呢。见下图:
image.png

2、字段非空
image.png
按照公式:327662+22=65536>65535,所以建表失败

字符集为utf8(1个字段)

1、utf8一个字符,可能占用1-3个字节,我们定义一个比较大的长度,进行试验一下
image.png
结果报错,显示max=21845,那我们把列的字符数长度定义21845就可以了吗,尝试一下
image.png
结果还是告诉我行长度太大了,原理同上,我们计算一下
(x3)+22=65535 ;计算得x=21843.6,所以下方的建表语句可以成功。
image.png

总结

1、以上只举了2个例子,其他字符集编码的如GBK、utf8mb4,可以自己去做实验
2、虽然字段少的情况下,varchar可以定义很大,但是不建议定义很大,因为长度比较大,会把真实的数据存到溢出页上,行上存部分数据或者数据的地址(行格式不同存的数据不同),这样会影响性能。