阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

MySQL数据库字段长度问题理解

98次阅读
没有评论

共计 2300 个字符,预计需要花费 6 分钟才能阅读完成。

在 MySQL 的表结构设计中,突然想起来几个地方碰到的问题比较多,大体来说一个就是字符集,一个就是数据类型。而字符集和数据类型结合起来,就有一个蛮有意思的细节,那就是行长度的问题。

比如我们创建一个表使用了 varchar 的类型,如果指定为 gbk,表里含有一个字段,可以指定为 32766 字节,如果再长一些就不行了。

其中的计算方式就需要理解了,因为 varhcar 类型长度大于 255,所以需要 2 个字节存储值的长度,而 MySQL 里面的页的单位是 16k, 使用了 IOT 的方式来存储。所以如果超过了这个长度,那就会有溢出的情况,和 Oracle 的 overflow 很类似。

所以对于 gbk 类型,行长度最大为 65535,则 varchar 列的最大长度算法就是 (65535-2)/2 =32766.5,所以此处就是 32766 了。

> create table test_char(v varchar(32766)) charset=gbk;
 Query OK, 0 rows affected (0.00 sec)
 > create table test_char1(v varchar(32767)) charset=gbk;
 ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs 而另外一种字符集,也是默认的字符集 latin1, 有些系统支持火星文的还是会喜欢用这种字符集。

它的长度就不一样了,对应是 1 字节,所以 varchar(32767) 是没有任何问题的,而最大长度就是 65532 了。
> create table test_char1(v varchar(32767)) charset=latin1;
 Query OK, 0 rows affected (0.01 sec)
 > create table test_char2(v varchar(65535)) charset=latin1;
 ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs 而对于 utf8 还是有很大的差别,对应的是 3 个字节,所以需要除以 3,按照(65535-2)/3,最大值就是 21844 了。
> create table test_char2(v varchar(21844)) charset=utf8;   
 Query OK, 0 rows affected (0.00 sec)
 > create table test_char3(v varchar(21845)) charset=utf8;
 ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs 上面的场景相对来说会有一些局限性,那么我们引入表结构的设计。

如果是 gbk 字符集,含有下面的几个字段,则 memo 字段的 varchar 类型最大长度是多少?

> create table test_char3(id int,name varchar(20),memo varchar(32766)) charset=gbk;
 ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs

这个问题还是如法炮制,应用之前的计算方式,数值型是 4 个字节,字符型乘以 2,含有字符型的长度小于 255,所以减去 1 即可,这样下来就是(65535-1-4-20*2-2)约等于 32743

> create table test_char3(id int,name varchar(20),memo varchar(32744)) charset=gbk;
 ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOB 两种测试结果可以简单对比一下。
> create table test_char3(id int,name varchar(20),memo varchar(32743)) charset=gbk;
 Query OK, 0 rows affected (0.01 sec)
 select (65535-1-4-20*2-2)/2;
 +———————-+
 | (65535-1-4-20*2-2)/2 |
 +———————-+
 |          32744.0000 |
 +———————-+
 1 row in set (0.00 sec)

整个过程还是需要考虑到这些点的,否则前期不够重视,在后面去做扩展的时候就会有很大的限制。

本文永久更新链接地址 :http://www.linuxidc.com/Linux/2017-06/145311.htm

正文完
星哥说事-微信公众号
post-qrcode
 
星锅
版权声明:本站原创文章,由 星锅 2022-01-22发表,共计2300字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中