mysql中 VARCHAR(N)类型,GBK编码,utf8编码,则N最大值,字符串长度问题

[ 2019-12-12 10:37:30 | 作者: admin ]
字号: | |
p.s. 在mysql5中,varchar(20)就表示可以放20个字(数字英文或汉字),无论编码是UTF8,GBK,都可以放20个。mysql会自动分配存储字节空间

如果是汉字,GBK编码下1汉字=2byte, varchar(20)会占用40字节,UTF8编码1汉字=3byte, varchar(20)会占用60字节,UTF8mb4编码1汉字=4byte, varchar(20)会占用80字节

有道面试题:若一张表中只有一个字段VARCHAR(N)类型,utf8编码,则N最大值为多少?
先明白计算的一些规则限制

mysql 4.0版本以下,varchar(20),指的是20字节,如果存放UTF8汉字时,只能存6个(每个汉字3字节)
mysql 5.0版本以上,varchar(20),指的是20字符,无论存放的是数字、字母还是UTF8汉字(每个汉字3字节),都可以存放20个,最大大小是65532字节

① 存储限制
        需要额外地在长度列表上存放实际的字符长度:小于255为1个字节,大于255则要2个字节
② 编码限制
        gbk:每个字符最多占用2个字节
        utf8:每个字符最多占用3个字节
③ 长度限制
        MySQL定义行的长度不能超过65535,这个限制了列的数目,比如char(255) utf8
        那么列的数目最多有65535/(255*3)=85,列的数目可以从这里得到依据
     
行长度计算公式如下:
row length = 1
                    + (sum of column lengths)
                    + (number of NULL columns + delete_flag + 7)/8
                    + (number of variable-length columns)
① 对于MyISAM,需要额外1个位来记录值是否为NULL;对于InnoDB,没有区别
② 对于row_format为fixed,delete_flag为1;对于row_format=dynamic,delete_flag为0

根据这个公式,我们便能够解答开头N的最大值:(65535-1-2)/3
减1是因为实际存储从第2个字节开始
减2则因为要在列表长度存储实际字符长度
除3是因为utf8编码限制

再来一道:
create table t4(c int, c2 char(30), c3 varchar(N)) charset=utf8;
N的最大值:(65535-1-2-4-30*3)/3

则此处N的最大值为 (65535-1-2-4-30*3)/3=21812

减1和减2与上例相同;

减4的原因是int类型的c占4个字节;

减30*3的原因是char(30)占用90个字节,编码是utf8。

  如果被varchar超过上述的b规则,被强转成text类型,则每个字段占用定义长度为11字节,当然这已经不是“varchar”了
[最后修改由 admin, 于 2020-06-08 22:15:59]
评论Feed 评论Feed: http://blog.xg98.com/feed.asp?q=comment&id=2633

这篇日志没有评论。

此日志不可发表评论。