mysql 的 varchar 的最大有效长度

转载 · jin7 · 2020-09-24 · 原文

latin1 字符集, 65532

utf8 字符集, 21844

utf8mb4 字符集, 16128

也就是说如果设定为 utf8mb4 字符集, varchar 最多能存 16128 个字符, 不论是中文还是英文.

(65535-1-2)/1=65532
#只有一个字段时,max(N)=65535-2-1,2个字节用于标识实际占用长度(16bit),1个字节用于标识字段NULL,所以max(N)=65532。

(65535-1-2)/3=21844

(65535-1-2)/4=16383 !=16128, 不满足这个"公式"

以下内容来自(作者:SaintTinyBoy)
https://my.oschina.net/u/2302503/blog/1620789

下面的实验字符集为latin1。

如果数据表只有一个varchar字段且该字段DEFAULT NULL,那么该varchar字段的最大长度为65532个字节,即65535-2-1=65532 byte。

执行以下将报错

create table test3(a varchar(65533));

只有一个字段时,max(N)=65535-2-1,2个字节用于标识实际占用长度(16bit),1个字节用于标识字段NULL,所以max(N)=65532。

拥有9个字段时,并且都是默认为NULL,最后一个字段i的max(N) = 65535 - 29 - 1 - 81898 = 4。

执行以下将报错

create table test3(a varchar(8189) default null,b varchar(8189) default null,c varchar(8189),d varchar(8189),e varchar(8189),f varchar(8189),g varchar(8189),h varchar(8189),i varchar(5));

如果前8个字段默认都是NOT NULL,最后一个字段i的max(N) = 65535 - 29 - 81898 = 5

以下将执行成功

 create table test4(a varchar(8189) not null,b varchar(8189) not null ,c varchar(8189) not null,d varchar(8189) not null,e varchar(8189) not null,f varchar(8189) not null,g varchar(8189) not null,h varchar(8189) not null,i varchar(5));

如果前8个字段都是NULL,最后一个字段 not null,最后一个字段i的max(N) = 65535 - 29 - 81898 = 5,说明只要在创建表时,存在任意一个字段not null,就不会占用NULL标识位,节约1个字节。

如果字段类型混搭 & 默认都是NULL,max(N) = 65535-4-2-1=65528

以下将执行报错

create table test4(a varchar(65529),age int);

如果有一个为not null,max(N) = 65535-4-2-1 = 65528
以下将执行报错

create table test4(a varchar(65529) not null,age int);

以上介绍的是行数据的最大长度,下面介绍的是创建索引时key的长度计算

create table test0(a varchar(10),b varchar(10));
create index ab_idx on test0(a,b);
explain select a from test0;

key=(10+2+1)2 = 26个字节;2个字节用于标识实际占用长度(16bit),1个字节用于标识字段NULL。如果将一个字段修改成not null,则key=102 + 2*2+ 1 = 25,少一个字节是因为字段a为not null,节省了一个字节的占用。key的计算依然和字符集有关系,这里使用的是latin1。

alter table test0 modify a varchar(10) not null;