mysql中varchar能够存储可变长度的字符串。过去我做的诸多业务中,一般存储短字符串的需求,都会使用varchar类型,并且定义长度为255,也就是varchar(255)。

不过为了探究varchar这种类型到底是怎么存储的,它的最大长度能达到多少,我决定区翻一下mysql文档学习一下。

varchar怎么存储

经过一番了解,varchar最大能存储的长度为65535字节。存储字符串的时候,会将字符串的长度存在首部,接着才是内容。

当varchar存储的字符个数小于或等于255的时候,首部需要一个字节来记录字符的个数。当内容大于255的字符的时候,首部需要2个自己来保存长度。

varchar能存的最大字符长度

理论上,varchar能够存储65535个字节,但是由于首部会占用两个字节,因此这会让varchar可用的存储空间变成了65533字节。如果定义的列是非空话,那最大是65533,如果定义的列允许NULL,那么null会占用一个额外的字节,因此最大只能存储65532个字节。

字节并不等于字符长度,varchar括号里面跟着的是字符长度,如果字符集是utf8的话,每一个字符统一会占用3个字节的长度,不管是汉子还是英文字符,因此最大能够存储的长度是65533/3 = 21844。如果字符集是utf8mb4那最大存储长度就更小了,为65533/4=16383。

试验验证UTF8下的最大长度

连接mysql,输入status,看到环境中mysql版本是5.6.34。

先创建一个测试的数据库

mysql> create database imhuchao default charset utf8;

Query OK, 1 row affected (0.00 sec)

创建一个含有varchar列的表,试试65535.

mysql> create table test(v1 varchar(65535) not null);

ERROR 1074 (42000): Column length too big for column 'v1' (max = 21845); use BLOB or TEXT instead

很显然,这样会出错。提示我们最大为21845,这个只是简单的用65535/3计算了一下,这是不准确的。我们用21845的话,很明显这还是错误的。

mysql> create table test(v1 varchar(21845) not null);

ERROR 1118 (42000): 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

mysql的行大小最大为65535,很明显21845*3+2已经超过了这个大小。因此如果是utf8字符集,varchar能存的字符个数最多只有21844

mysql> create table test(v1 varchar(21844) not null);

Query OK, 0 rows affected (0.01 sec)

试验验证latin1下的最大长度

定义一个非空列,看看最大长度

mysql> create table test2(v1 varchar(65533) not null) default charset latin1;

Query OK, 0 rows affected (0.02 sec)

很明显,65533是可以达到的。

如果允许空的话,那将会出错

mysql> create table test3(v1 varchar(65533)) default charset latin1;

ERROR 1118 (42000): 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

允许空值,最大只能到65532

mysql> create table test3(v1 varchar(65532)) default charset latin1;

Query OK, 0 rows affected (0.01 sec)