MySQL定義VARCHAR(M)最多可以是65535個字節(jié),M表示的是「字符數(shù)量」,但是實際存儲中并不能存儲那么多字節(jié)。如果一個字段超過了65535個字節(jié),可以選擇使用TEXT或者BLOB類型。
對于一個列來說,除了存儲本身數(shù)據(jù)以外還要存儲MySQL定義的數(shù)據(jù),根據(jù)行記錄格式,VARCHAR(M)存儲空間由3部分構(gòu)成,分別為真實數(shù)據(jù)、真實數(shù)據(jù)的長度、NULL值標識。真實數(shù)據(jù)是用戶要存儲的數(shù)據(jù),真實數(shù)據(jù)的長度是用戶存儲的這部分數(shù)據(jù)的長度,NULL值標識是該列是否允許為NULL。其中真實數(shù)據(jù)的長度會占用2個字節(jié),NULL值標識占用1個字節(jié),如果該列NOT NULL則NULL值標識不占用空間。
就是說當該列允許為NULL時,最多只能存儲65535-2-1=65532個字節(jié),如果該列為NOT NULL時,最多只能存儲65535-2=65533個字節(jié)。
VARCHAR(M)最多能存儲多少真實數(shù)據(jù)(也就是M的最大取值)跟字段采用的字符集有關(guān),以下就拿字符集utf8、gbk、utf8mb4說明一下:
- utf8字符集:MySQL中的utf8字符集跟標準的utf-8字符集是不同的。MySQL中的utf8字符集一個字符最多占3個字節(jié),而標準的utf-8字符集是最多占4個字節(jié)。在字段允許為NULL的情況下,計算最多能存儲多少真實數(shù)據(jù)的公式為(65535-2-1)÷3=21844,字段不允許為NULL的情況下,公式為(65535-2)÷3=21844.333,所以utf8字符集最多能存儲21844個字符。 由于字段允許為NULL就只占一個字節(jié),在字符集最多占用字節(jié)數(shù)大于1的情況下,計算出來的結(jié)果中會有小數(shù),小數(shù)最終也會被舍棄,所以就先不考慮字段是否允許為NULL值了。
- gbk字符集:gbk字符集中一個字符最多占2個字節(jié)。最多能存儲多少真實數(shù)據(jù)的公式為(65535-2)÷2=32766,所以M的最大值32766。
- utf8mb4字符集:utf8mb4字符集中一個字符最多占用4個字節(jié)。最多能存儲多少真實數(shù)據(jù)的公式為(65535-2)÷4=16383.25,小數(shù)舍棄就是最多能存儲16383個字符。
實際上在設(shè)置VARCHAR(M)最多存儲多少字符時,要在上面計算結(jié)果的基礎(chǔ)上「減一」。
如果字段設(shè)置的長度超過了實際能存儲的長度,MySQL就是報下面這個錯誤
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
最后總結(jié)一下,VARCHAR能最多能存儲多少真實數(shù)據(jù)跟字符編碼集有關(guān),最多能存儲多少個字符是個上限值,實際存儲不了那么多,要在上限值的基礎(chǔ)上減一。