varchar有最大長度嗎

 

先說結論,mysql 中的 varchar 是有最大長度限制的,這個值是 65535 個字節。

 

varchar(100),這個 100 的單位是啥,這個單位其實在不同版本中是不一樣的。

 

在早期低版本中代表的是字節,具體哪個版本我也沒去驗證了,後來被改成了字符,不過可以肯定的是在 5.1 版本後, varchar(100) 就是指 100 個字符。

 

說到 varchar ,一般都會拿 char 來做比較說明。

 

char 是固定長度,其單位也是字符,比如 char(10),就表示不管你給的什麼值,都會被 mysql 固定保存成 10 個字符。

 

如果給的字符長度小於 10,那麼在尾部就會自動用空格補齊。

 

如果大於 10,在嚴格模式(strict sql mode)下就會報錯,在非嚴格模式下就會對內容做自動截取操作。

 

另外 char 也是有最大長度限制的,最大長度爲 255, 即 char 類型最多隻能保存 255 個字符,char(256) 這都是錯誤的寫法,可以看下面的例子。

##創建一個表,同時聲明address字段長度爲256會報錯,最大爲255mysql> 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 個字節來存儲字符的長度,這個值被稱作前綴

 

也就是說在 varchar 類型中,除了字符本身實際佔用的空間外,還需要 1 個或 2 個字節來聲明這個字符的長度。

 

如果存儲的值小於 255 個字節,則使用 1 個字節來存儲前綴,如果大於 255 個字節則使用 2 個字節來存儲前綴。

 

關於字符集和字節的關係,以及字節 (byte) 與位 (bit) 的關係。

1 byte (字節) = 8 bit (位)
2^8 = 256
所以計算機裏常見的 255、256 臨界值絕大多數與這個有關
1 個字節具體佔多大的空間,這與所使用的字符集有關係
比如 latin1 單字節字符集,1 個字符即佔 1 個字節
我們常見的 GBK、UTF8、UTF8-MB4 這些都是多字節字符集
GBK :一個字符最多佔 2 個字節UTF8:一個字符最多佔 3 個字節UTF8MB4:一個字符最多佔 4 個字節

 

好了,再堅持一會,回到文章開頭的問題,爲啥 varchar 最大長度是 65535 個字節呢,其實這個是受 mysql 另一個規則限制導致的,mysql 規定了每行數據大小不能超過 65535 個字節

 

另外還有一個小問題,一個字段如果允許爲 null ,在 mysql 中也是需要增加額外空間來單獨標識的,反之則不需要這個額外空間,至於這個空間大小具體是怎麼計算的,我目前也還沒有研究過。

 

結合上面說的幾點,下面來通過幾個實例來驗證下。

##字符集設置爲latin1,1個字符=1個字節,字段允許爲nullmysql> 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 (行最大字節數) - 255*3 (一個字符最多佔 3 個字節) = 64770,

 

然後再減去 2 個長度前綴字節,

 

64770 - 2 = 64768,

 

最後再算出 varchar 最大字符數爲 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)

 

好了,關於 varchar 的最大長度問題就聊到這了,文中如有錯誤,歡迎大家批評指出,更歡迎大家交流討論,如果文章對你有幫助,點個贊表示對我的支持哈,感謝。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章