mysql5.1后且字符集是utf-8,varchar最大长度是21845个字符,换算成字节是6553565532/3 = 21844char最大长度255个字符varchar和char是代表字符长度之外,其余的类型都是代表字节长度。varchar(255)
255的单位在不同版本不一样
在之前的版本单位是字节,可以确定的是从mysql5.1开始,单位是字符
另外mysql规定:每行数据大小不能超过65535个字节,所以varchar实际最大长度受其他字段长度影响
BLOB 和 TEXT 列不算入单行长度限制,只对行大小限制贡献9到12个字节,因为它们的内容与行的其余部分分开存储
说到varchar,一般都会拿char来做比较说明。
char是固定长度,其单位也是字符,比如char(10),就表示不管你给的什么值,都会被mysql固定保存成10个字符。
小于 10,那么在尾部就会自动用空格补齐。大于10,在严格模式(strict sql mode)下就会报错,在非严格模式下就会对内容做自动截取操作。另外char也是有最大长度限制的,最大长度为255, 即char类型最多只能保存255个字符,char(256)这都是错误的写法
可以看下面的例子。
##创建一个表,同时声明address字段长度为256会报错,最大为255
mysql> create table test2 ( address char(256) );
ERROR 1074 (42000): Column length too big for column 'address' (max = 255); use BLOB or TEXT instead
下面是char和varchar对于同一个字符所需要的不同的存储空间,这里假设使用的是 latin1 单字节字符集。
值 CHAR(4) 存储空间大小(字节) VARCHAR(4) 存储空间大小(字节)
'' ' ' 4 bytes '' 1 byte
'ab' 'ab ' 4 bytes 'ab' 3 bytes
'abcd' 'abcd' 4 bytes 'abcd' 5 bytes
'abcdef' 'abcd' 4 bytes 'abcd' 5 bytes
varchar 的存储空间会比字符的实际长度多 1 个字节,
这是因为 varchar 需要额外增加 1 到 2 个字节来存储字符的长度,这个值被称作前缀。
如果存储的值小于 255 个字节,则使用 1 个字节来存储前缀,如果大于 255 个字节则使用 2 个字节来存储前缀。
1 byte (字节) = 8 bit (位)
2^8 = 256
所以计算机里常见的 255、256 临界值绝大多数与这个有关
1 个字符具体占多大的空间(字节),这与所使用的字符集有关系
比如 latin1 单字节字符集,1 个字符即占 1 个字节
我们常见的 GBK、UTF8、UTF8-MB4 这些都是多字节字符集
GBK :一个字符最多占 2 个字节
UTF8:一个字符最多占 3 个字节
UTF8MB4:一个字符最多占 4 个字节
UTF-8使用1~4字节为每个字符编码:
中文占三字节(包括标点符号)
英文字符占一字节(包括标点符号)
Unicode编码:
中文(含繁体)占二字节
英文占二字节
UTF8MB4:
英文占一个字符
中文占三个字符
特殊符号,支持四个字符 例如表情符号
mysql排序规则
tf8_general_ci 不区分大小写,这个你在注册用户名和邮箱的时候就要使用。
utf8_general_cs 区分大小写,如果用户名和邮箱用这个 就会照成不良后果
utf8_bin:字符串每个字符串用二进制数据编译存储。 区分大小写,而且可以存二进制的内容
utf8_unicode_ci和utf8_general_ci对中、英文来说没有实质的差别。
utf8_general_ci校对速度快,但准确度稍差。
utf8_unicode_ci准确度高,但校对速度稍慢。
一个字段如果允许为null,在mysql中也是需要增加额外空间来单独标识的,反之则不需要这个额外空间。
验证一下
##字符集设置为latin1,1个字符=1个字节,字段允许为null
mysql> create table test ( address varchar(65536) default null ) charset=latin1;
ERROR 1074 (42000): Column length too big for column 'address' (max = 65535); use BLOB or TEXT instead
##减去varchar前缀长度标识2个字节,还是报错,说明null标识也占用了空间
mysql> create table test ( address varchar(65533) default null ) 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
##把字段设置为非空即可建表成功
mysql> create table test ( address varchar(65533) not null ) charset=latin1;
Query OK, 0 rows affected (0.01 sec)
##如果字符集设置为UTF8,那么 max=65535/3=21845,一个字符最多占3个字节
mysql> create table test2 ( address varchar(65533) not null ) charset=UTF8;
ERROR 1074 (42000): Column length too big for column 'address' (max = 21845); use BLOB or TEXT instead
基于上面几个实例,可以得出计算varchar最大长度限制的公式。
varchar 最大长度限制 = (行最大字节数(65535) - null 标识字节数 - 长度前缀字节数(1或2)) / 字符集单字符占用最多字节数
为什么长度前缀 1 或 2 个字节就够用了呢,因为 2 个字节的话,2^16 = 65536,
这已经超过 mysql 行最大字节数 65535 的限制了,所以 1 到 2 个字节就够用了。
看一个具体的实例:
创建一个表,采用UTF8字符集,添加两个非空字段,分别为char和varchar类型,char类型长度给定为255。
那么varchar类型字段的最大字节数应该就是:
65535(行最大字节数) - 0(非空字符) - 2(长度前缀) - 255(char字段长度) * 3(一个字符最大占用字节) = 64768
最后除以3
64768 / 3 = 21589.33
# 字符数21590超过最大字符数会报错
mysql> create table test4 (name char(255) not null, address varchar(21590) not null ) charset=utf8;
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
# 字符数21589则刚好能创建成功
mysql> create table test4 (name char(255) not null, address varchar(21589) not null ) charset=utf8;
Query OK, 0 rows affected, 1 warning (0.02 sec)