MySQL 性能調優(二):字符類型選型實戰——CHAR vs VARCHAR 與字符集影響
核心結論先行
- 固定長度、高頻讀寫、長度固定(如 MD5 32 位、UUID 36 位、手機號 11 位) → CHAR。
- 長度變化大、平均長度遠小於最大長度(如地址、描述、評論) → VARCHAR。
- 字符集直接決定最大列長度上限:UTF8MB4 下 VARCHAR 最大約 21,844 字符;GBK 下約 32,766 字符。
1. 存儲機制對比
| 特性 | CHAR(N) | VARCHAR(N) |
| 長度 | 固定 N 字符 | 變長,實際長度 L |
| 空間佔用 | N × 字符集字節數 | L × 字符集字節數 + 1~2 字節長度前綴 |
| 不足補齊 | 右側空格填充,讀取時去除 | 無填充 |
| 尾部空格 | 不可存儲尾部空格 | 可存儲 |
| 檢索速度 | 略快(固定偏移定位) | 略慢 |
2. 字符集對最大長度的限制(單表行大小 65,535 字節)
GBK(雙字節)
-- 單列 VARCHAR 最大字符數
(65535 - 2) / 2 = 32766 字符
-- 含 1 字節長度前綴(≤255)或 2 字節(>255)
UTF8 / UTF8MB4(三/四字節)
-- UTF8 (3 字節)
(65535 - 2) / 3 = 21844 字符
-- UTF8MB4 (4 字節)
(65535 - 2) / 4 = 16383 字符
多列組合時
-- 例:20 個 VARCHAR(20) CHARSET GBK + 1 個 INT + 1 個 BIGINT
(65535 - 4 - 20*2 - 1 - 8 - 2) / 2 = 32740 字符/列(理論上限)
3. 選型決策樹
字段長度是否固定?
├─ 是 → 是否極短(≤30字符)且高頻讀寫?
│ ├─ 是 → CHAR(N) (如 MD5、UUID、手機號、郵編、狀態碼)
│ └─ 否 → VARCHAR(N) (雖固定但較長,CHAR 浪費空間)
└─ 否 → VARCHAR(N) (地址、描述、JSON 片段、標籤等)
4. 實戰案例
| 業務字段 | 建議類型 | 理由 |
| 用戶密碼 MD5 | CHAR(32) | 固定 32 字符,高頻比對,CHAR 省 1 字節前綴 |
| 手機號 | CHAR(11) | 固定 11 位,索引命中率高 |
| 收貨地址 | VARCHAR(128) | 長度變化大,平均 30 字符 |
| 商品標題 | VARCHAR(64) | 長度不一,VARCHAR 節省空間 |
| 文章內容 | TEXT / MEDIUMTEXT | 超過 VARCHAR 上限,用 TEXT 族 |
5. 避坑指南
- 不要用 CHAR(255) 存長文本:極度浪費空間,導致表掃描極慢。
- UTF8MB4 下 VARCHAR(255) 實際佔 1020 字節,加上前綴 2 字節,單行 10+ 列即逼近 65KB 上限。
- ALTER TABLE MODIFY COLUMN 縮短 VARCHAR 前必先
SELECT MAX(CHAR_LENGTH(col)) 確認數據不超限。
- 索引長度限制:InnoDB 單列索引 ≤ 767 字節(或開啟
innodb_large_prefix 後 3072 字節),UTF8MB4 下 VARCHAR(191) 即達 767 字節。
一句話總結: 固定短用 CHAR,變長用 VARCHAR,時刻牢記字符集放大倍數與 65KB 行上限,索引長度別超標。