先拋出官網(wǎng)答案:
In contrast to CHAR, VARCHAR values are stored as a 1-byte or 2-byte length prefix plus data. The length prefix indicates the number of bytes in the value. A column uses one length byte if values require no more than 255 bytes, two length bytes if values may require more than 255 bytes.
簡單翻譯一下就是
char, varchar類型的值,會有一個長度標識位來存值長度。
當定義varchar長度小于等于255時,長度標識位需要一個字節(jié);
當大于255時,長度標識位需要兩個字節(jié)
也就是說,當我們定義一個varchar(255)的字段時,其實它真實使用的空間是256(255+1)字節(jié);(注意,字段非空,latin1編碼)
當我們定義一個一個varchar(256)字段時,它真實使用的空間是258(256+2)字節(jié)
簡單實踐證明一下:
- 試著創(chuàng)建一個字段長度超過mysql限制的表,從系統(tǒng)提示知道,列長度不能超過65535
mysql> create table test_varchar_length(v varchar(65536) not null) CHARSET=latin1;
ERROR 1074 (42000): Column length too big for column 'v' (max = 65535); use BLOB or TEXT instead
- 創(chuàng)建一個字段長度小于max, 65534的表,繼續(xù)失敗
mysql> create table test_varchar_length(v varchar(65534) not 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
- 創(chuàng)建一個65533的表,65533+2=65535(max), 成功
mysql> create table test_varchar_length(v varchar(65533) not null) CHARSET=latin1;
Query OK, 0 rows affected (0.05 sec)
(注意,上面的例子字符集用的latin1,如果使用utf8mb4,在mysql中一個長度需要四個字節(jié),計算臨界值時需要考慮。)
有興趣的朋友還可以試著把字段定于成 default null試試,會發(fā)現(xiàn)結(jié)果又不一樣,可以自己探索下原因
參考:
stackoverflow: Why historically do people use 255 not 256 for database field magnitudes?
MySQL中VARCHAR最大長度是多少?CHAR和VARCHAR有哪些區(qū)別?