大家都知道用 varchar 比用 char 類型更省空間(不過性能略有下降,char查詢更快),相對于定長的 char ,varchar 存儲分為兩部分:
varchar字段長度 = 字符串長度值 + 實(shí)際數(shù)據(jù)長度 N。
字符串長度值視實(shí)際數(shù)據(jù)長度,需占用 1 或 2 個字節(jié)存儲。所以,我們得出:
當(dāng)實(shí)際數(shù)據(jù)長度 <= 255 時,varchar字段長度 = 1 + N;
當(dāng)實(shí)際數(shù)據(jù)長度 > 255 時,varchar字段長度 = 2 + N;
因此,在設(shè)計(jì)數(shù)據(jù)表時,varchar(64) 和 varchar(255) 在實(shí)際應(yīng)用中占用存儲是一樣的;varchar(256) 和 varchar(50000) 也是一樣的。
所以,varchar(n)的分水嶺就是255。varchar(n),在255以下,無論設(shè)置n是多少都沒區(qū)別。在varchar(255)以上,直到最大值,無論設(shè)置n是多少也沒區(qū)別
比如有些數(shù)據(jù)庫里設(shè)置varchar(1023)之類的,其實(shí)這個和varchar(1024),varchar(1234)什么的都沒有任何區(qū)別!1023并不會比1024少用一個字節(jié),1023并不是一個特殊值,只有255才是。
所以設(shè)計(jì)數(shù)據(jù)庫字段的時候,只需要考慮字符串是否會超過255就可以了,其他不用考慮。需要注意的是,這里varchar(n)的n是字符長度,不是字節(jié)長度,實(shí)際占用空間跟字符編碼有關(guān)。
那么問題來了,為什么不在設(shè)計(jì)時就盡可能把最大長度設(shè)置大一些,免得未來長度不夠惹麻煩呢?比如,用戶名能用 varchar(200) 就不必用 varchar(20),存儲稍大一些字符串的字段,能用 varchar(2000) 就不必斤斤計(jì)較用 varchar(256)。
這么長的空間,能存儲多少漢字呢?如果采用 UTF-8 編碼存儲,每個漢字占用 3 個字節(jié);如果采用可以放表情的 utf8mb4,每個漢字占用 4字節(jié)。
當(dāng)然,長度也不是可以無限長,varchar 字段長度在設(shè)計(jì)表時需要考慮下面因素:
- UTF-8 狀態(tài)下,單個 varchar 長度不能超過 (65535 - 2) / 3 = 21844;
- 一行數(shù)據(jù)所有字段長度加起來不能超過 65535;
- 如果需要存儲超長文本,考慮使用 text 類型,只存儲指針長度
所以,知道了上面的知識點(diǎn)后,下次在設(shè)計(jì)數(shù)據(jù)庫的時候,就不必太糾結(jié) varchar(N) 中的 N 值了,條件允許的前提下,盡可能設(shè)大一些吧。
所以不要再吝嗇 varchar 的長度了。