最近在工作中遇到一個問題,項目中數(shù)據(jù)庫的一個字段設定的長度要被用盡了,需要調(diào)整.這個字段是varchar類型的.于是直面而來的一個問題就是:varchar類型字段長度到底能設置為多大?
首先確定的一點是mysql中varchar(n) ,這個n代表的是字符數(shù)(不是字節(jié)數(shù)).
舉個例子:
| Table | Create Table |
|---|---|
| user | CREATE TABLE `user` ( `id` bigint(20) NOT NULL, `name` varchar(5) NOT NULL, `age` smallint(6) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
insert into user values (111,'我是中國人',20);
1 row affected in 51 ms
增加一個字符
insert into user values (222,'我是中國人呢',20);
[22001][1406] Data truncation: Data too long for column 'name' at row 1
提示超長
insert into user values (222,'abcde',20);
1 row affected in 61 ms
增加一個字符
insert into user values (333,'abcdef',20);
[22001][1406] Data truncation: Data too long for column 'name' at row 1
提示超長
可以看出 n 代表的是字符數(shù)
那這個n最大是多少呢?
計算公式為:
# 21840.6667 = 21840
select (65535 - 8 - 2 - 1 -2) / 3;
解析:
varchar的設定受到mysql對一行數(shù)據(jù)允許最大字節(jié)數(shù)的限制.
mysql要求一個行的定義長度不超過65535(2^16 - 1) 所以有65535
減8的原因是字段id的bigint類型占用8個字節(jié).
減2的原因是varchar頭部的2個字節(jié)表示長度(超過255為2,小于255為1).
減1的原因是實際行的存儲從第2個字節(jié)開始.
減2的原因是字段age的smallInt類型占用2個字節(jié).
除以3的原因是一個utf8字符通常占用3個字節(jié).
驗證:
alter table user modify name varchar(21841);
[42000][1118] 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
更換為21840
alter table user modify name varchar(21840);
2 rows affected in 165 ms
| Field | Type | Null | Key | Default | Extra |
|---|---|---|---|---|---|
| id | bigint(20) | NO | PRI | NULL | |
| name | varchar(21840) | YES | NULL | ||
| age | smallint(6) | YES | NULL |