許多開發者對 VARCHAR 與 TEXT 的區別存在誤解。本文從存儲機制、長度限制、效能表現、最佳實踐四個維度徹底釐清兩者差異,助你做出正確選型。
| 特性 | VARCHAR(M) | TEXT |
|---|---|---|
| 最大長度 | 65,535 字節(受行大小限制) | 65,535 字符(約 64KB) |
| 存儲開銷 | L + 1~2 字節(長度前綴) | L + 2 字節 |
| 是否在行內存儲 | 是(若行總長 < 65,535) | 否(溢出頁存儲,行內只存 20 字節指針) |
| 可建索引 | 全長/前綴索引均可 | 僅前綴索引 |
| 預設值支援 | 支援 | 5.7+ 才支援 |
| 字符集影響 | 字節上限固定,字符數隨字符集變化 | 字符上限固定 |
VARCHAR 佔用行內空間,若定義過大會導致建表失敗或隱式轉為 TEXT。VARCHAR ≤ 255 字節用 1 字節前綴,> 255 用 2 字節;TEXT 固定 2 字節。TEXT 永遠在溢出頁,讀取需額外 I/O;VARCHAR 若行長超限也會溢出。VARCHAR 可建全長唯一索引;TEXT 必須指定前綴長度(如 INDEX idx_title (title(50)))。VARCHAR 明顯快於溢出頁的 TEXT,尤其在 SELECT * 掃描大表時。VARCHAR 可直接使用內存排序;TEXT 常需臨時表 + 磁盤排序(Using filesort)。LIKE '%keyword%' 兩者皆無法用索引,但 VARCHAR 因行內存儲,全表掃描 I/O 較少。誤區 1:「
VARCHAR(65535)能存 65535 字符」
→ 錯。上限是 65,535 字節,UTF-8 下一字符 3 字節,實際僅能存 ~21,844 字符,且還要扣除其他欄位與行開銷。誤區 2:「
TEXT查詢比VARCHAR慢,所以不用」
→ 片面。大文本場景TEXT反而避免行溢出導致的隱式轉換與鎖爭用,配合INDEX (col(50))滿足前綴搜索即可。誤區 3:「MySQL 5.0.3 後
VARCHAR變長 65535,就不用TEXT了」
→ 忽略了行大小硬限制與溢出頁機制,大字段強行VARCHAR反而傷效能。
遵循 「能用 VARCHAR 就不用 TEXT,長度可預估用 VARCHAR,超長不可控用 TEXT」 原則。建表前先估算單行總長,必要時垂直拆分大字段至獨立表(一對一),兼顧主表查詢效能與大文本存儲靈活性。