VARCHAR(M) 中的 M 代表字符數而非字節數,但實際存儲受字符集編碼和行長度 65535 字節雙重限制。本文系統梳理 VARCHAR 長度計算規則、不同字符集實際上限、超限自動轉 TEXT 機制、CHAR/VARCHAR/TEXT 選型決策樹。
| 定義 | 字符集 | 最大字符數 | 說明 |
|---|---|---|---|
| VARCHAR(65535) | latin1 (1字節/字符) | 65532 | 行長度上限 65535 - 1-2字節長度前綴 - NULL標誌 |
| VARCHAR(65535) | utf8 (3字節/字符) | 21844 | 65532 / 3 向下取整 |
| VARCHAR(65535) | utf8mb4 (4字節/字符) | 16383 | 65532 / 4 向下取整 |
| VARCHAR(21845) | utf8 | 報錯 | 超過 65532 字節行長度限制,自動轉 MEDIUMTEXT |
實際存儲字節數 = 字符實際字節長度 + 長度前綴字節數
長度前綴 = 1 字節 (M ≤ 255) 或 2 字節 (M > 255)
-- 示例:utf8mb4 表,VARCHAR(100) 存 'abc' (3字符)
-- 字符字節 = 3 × 4 = 12 字節
-- 前綴 = 1 字節 (100 ≤ 255)
-- 總計 = 13 字節
| 版本 | VARCHAR 最大長度 | M 含義 | 中文存儲 |
|---|---|---|---|
| MySQL 4.1 以前 | 255 | 字節數 | VARCHAR(20) 存 6 個 UTF8 漢字 (20/3) |
| MySQL 5.0.3+ | 65,535 | 字符數 | VARCHAR(20) 存 20 個 UTF8 漢字 |
重大變更:5.0.3+ 將 M 從字節改為字符,並引入長度前綴機制,極大提升了多語言存儲能力。
M ≤ 65535M × max_bytes_per_char + length_prefix ≤ 65535CREATE TABLE t (
a VARCHAR(30000) CHARSET utf8mb4, -- 30000×4+2 = 120002 字節 → 超限!
b VARCHAR(30000) CHARSET utf8mb4
) ENGINE=InnoDB;
-- ERROR 1118 (42000): Row size too large (> 65535)
VARCHAR(M) 定義超過字節上限 → 自動轉為 MEDIUMTEXT + WarningCHAR(M) 超過 255 → 自動轉為 VARCHAR → 再超限轉 TEXTSHOW WARNINGS;| 維度 | CHAR(M) | VARCHAR(M) | TEXT |
|---|---|---|---|
| 長度特性 | 固定長度,右填充空格 | 變長,實際長度+前綴 | 大變長,1-4字節長度前綴 |
| 最大長度 | 255 字符 | 65535 字符 (受行長度限制) | 4GB (LONGTEXT) |
| 默認值 | 支持 | 支持 | 不支持 |
| 索引效率 | 最高 (固定偏移) | 高 | 需指定前綴長度 |
| 適用場景 | 固定代碼:MD5、UUID、ISO 代碼 | 通用業務字段:名稱、地址、描述 | 大文本:文章、日志、JSON 文檔 |
| InnoDB 建議 | 慎用 (佔用固定空間) | 首選 | 大文本必選 |
VARCHAR(128)、VARCHAR(255)、VARCHAR(500) 覆蓋 99% 場景,預留餘量。TEXT/MEDIUMTEXT/LONGTEXT,勿嘗試極大 VARCHAR。INDEX idx_a_b (a(50), b(20)) 使用前綴索引控制索引大小。SELECT MAX(CHAR_LENGTH(col)), MAX(LENGTH(col)) FROM t; 實際長度分布指導定義調整。VARCHAR(M) 的 M 是字符數上限,實際存儲按字符集字節數計算,受行長度 65535 字節硬性約束。utf8mb4 下單列最大約 16383 字符,多列共存須計算行長度和。選型原則:固定碼用 CHAR、業務變長用 VARCHAR、大文本用 TEXT、InnoDB 首選 VARCHAR。定期審計實際長度分布,精準調整定義,平衡空間與性能。