暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL的varchar字段长度可以大于4000吗?

程序员阿牛 2021-07-06
1706

点击蓝字获取更多精彩信息



前言

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

正文

我们先看下官方给出的答案:
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个字段)

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

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

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

根据上面的分析,我们在做一下实验,来验证我们说的对不对
1、字段可空时
65532可以建表成功

65533就建表失败

原因:整个表有字段可空时,需要有一个字节来存储该记录是否为空(严格意义上是:可空数量/8+1个字节)


2、字段不可空时

原因:整个表字段都不可空时,就不需要字节来记录存储是否为空了,因此这里65533可以成功。


字符集为latin1(2个字段)

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

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

2、字段非空
按照公式:32766*2+2*2=65536>65535,所以建表失败

字符集为utf8(1个字段)

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

总结

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

往期回顾


在看的,麻烦点一下再走吧
文章转载自程序员阿牛,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论