Oracle 字符類型選型看似簡單,實則暗藏性能與存儲陷阱。本文從底層存儲機制、查詢性能、遷移兼容三個維度,徹底解析 CHAR 與 VARCHAR2 的區別,給出落地選型建議。
| 維度 | CHAR(n) | VARCHAR2(n) |
|---|---|---|
| 長度特性 | 固定長度,不足右補空格 | 變長,實際長度 + 1~2 字節長度前綴 |
| 存儲示例 | CHAR(10) 存 'A' → 佔 10 字節('A' + 9 空格) | VARCHAR2(10) 存 'A' → 佔 2 字節(長度 1 + 'A') |
| 中文存儲 | 1 中文 = 2~3 字節(視字符集 AL32UTF8/AL16UTF16) | 同樣按實際字節數存儲 |
| 最大長度 | 2000 字節 | 4000 字節(12c+ MAX_STRING_SIZE=EXTENDED 可達 32767) |
| 比較語義 | 空格填充比較:'A' = 'A ' 為 TRUE | 非填充比較:'A' = 'A ' 為 FALSE |
| 索引行長度 | 固定,利於索引頁面緊湊 | 變長,可能導致行遷移 |
早期文檔稱「CHAR 定長,定位快;VARCHAR2 需解析長度,慢」。實測表明:
結論:現代 Oracle(10g+)優化器對 VARCHAR2 高度優化,**性能差異可忽略**,存儲空間與語義正確性才是決策關鍵。
SYS 系統表大量使用 CHAR,歷史包袱,**用戶表勿效仿**。CHAR 同 Oracle,VARCHAR 等同 VARCHAR2。CHAR(n) 固定長度,VARCHAR(n) 變長,無 VARCHAR2。CHAR/NCHAR 固定,VARCHAR/NVARCHAR 變長。@Column(length=10) 默認映射 VARCHAR2,強制 CHAR 需 columnDefinition="CHAR(10)"。IF 長度極其固定(如 MD5=32, UUID=36, 國標代碼=6)AND 高頻 JOIN/索引
→ 考慮 CHAR(n) // 極少數場景
ELSE IF 需要語義精確比較(尾部空格有意義)
→ VARCHAR2(n) // CHAR 會自動補空格導致語義偏差
ELSE IF 存儲中文/多語言/可變長文本
→ VARCHAR2(n) // 節省空間,語義直觀
ELSE
→ VARCHAR2(n) // 默認首選
CHAR,但需實測確認索引收益 > 空間浪費。CHAR 空格填充導致索引失效。CHAR → VARCHAR2 需 RTRIM 去除尾部空格,防止業務邏輯誤判。ALTER SYSTEM SET MAX_STRING_SIZE=EXTENDED SCOPE=SPFILE,突破 4000 字節限制。字符類型選型無銀彈,**VARCHAR2 是 99% 場景的正解**;CHAR 只屬於極少數「定長、高頻 JOIN、不介意空間換時間」的特定場景。理解底層語義,才能做出理性決策。