首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL CHAR vs VARCHAR 深度對比:存儲機制、效能權衡與選型決策指南

     編輯:MySQL 資料庫相關知識

字符型數據佔據資料庫 80%+ 存儲,CHAR(固定長度)與 VARCHAR(可變長度)選型直接影響空間效率、查詢效能與碎片管理。基於 MyISAM/InnoDB 存儲引擎機制,本文系統分析兩者差異並給出選型決策樹。

核心存儲機制差異

特性CHAR(n)VARCHAR(n)
長度特性固定 n 字符可變 0~n 字符
磁碟存儲固定佔用 n 字符空間(不足右側填充空格,讀取時去除)實際長度 + 1-2 字節長度前綴
記憶體處理固定塊固定塊 (按定義長度 n 分配,用於排序/臨時表)
更新行遷移無 (長度不變)可能導致行分裂/遷移、碎片
索引體積固定變動,但記憶體中按最大長度分配
支援 BLOB/TEXT否否 (但可存長字串)

效能權衡深度解析

空間效率:VARCHAR 勝出(通常)

  • 平均長度遠小於最大長度時,VARCHAR 顯著節省磁碟空間。
  • MyISAM ROW_FORMAT=FIXED 強制 VARCHAR 退化為固定長度存儲。

更新效能:CHAR 勝出

  • CHAR 更新不改變行長度,**原地更新**,無行遷移、無碎片。
  • VARCHAR 更新導致長度變化時,可能觸發:行分裂、頁分裂、碎片產生、二級索引維護開銷。

排序/臨時表/記憶體:CHAR 勝出

  • MySQL 內部排序、建立臨時表時,**按定義長度分配固定記憶體塊**。
  • VARCHAR(200) 實際存 10 字符,排序時仍佔 200 字符記憶體。
  • **禁忌:盲目設定過大 VARCHAR(1000) 存短字串**,嚴重浪費排序緩衝區。

碎片管理:CHAR 免維護

  • VARCHAR 高頻更新表需定期 OPTIMIZE TABLE 或 ALTER TABLE ... ENGINE=InnoDB 整理碎片。
  • CHAR 固定長度天然無碎片。

選型決策樹:4 條黃金法則

字段最大長度 ≤ 20 且長度相對固定?
├─ 是 → CHAR (如:MD5、UUID、身份證、手機、郵編、狀態碼、ISO 代碼)
└─ 否 → 繼續判斷

長度變化範圍窄(如 90-100 字符)?
├─ 是 → CHAR (避免 VARCHAR 更新遷移開銷)
└─ 否 → 繼續判斷

涉及頻繁排序、GROUP BY、UNION、臨時表?
├─ 是 → 傾向 CHAR 或 緊湊 VARCHAR(實際最大長度+10%)
└─ 否 → 繼續判斷

通用場景 → VARCHAR(實際業務最大長度 + 10% 冗餘)

經典場景對照表

場景推薦型別理由
MD5/SHA1 雜湊值CHAR(32)/CHAR(40)固定長度、高頻索引、無更新
手機號/身份證/ISBNCHAR(11/18/13)固定長度、精確匹配
用戶名/暱稱VARCHAR(30~50)長度變化大、較少更新
文章標題VARCHAR(200)變長、偶爾更新
文章內容/評論TEXT / MEDIUMTEXT超過 65535 字節
URL/路徑VARCHAR(255~500)變長、可建前綴索引
郵編/國家代碼CHAR(6)/CHAR(2)固定長度、高頻篩選
JSON 片段JSON (5.7+) / TEXT結構化查詢支援

特殊陷阱:CHAR(1) vs VARCHAR(1)

  • 兩者僅能存單字符,但 VARCHAR(1) 額外佔用 **1 字節長度前綴**。
  • 單字符旗標欄位(Y/N、0/1、M/F)**強烈建議 CHAR(1)**。

InnoDB 額外考量

  • InnoDB 行溢出機制:VARCHAR 超過 768 字節可能移至溢出頁,CHAR 固定長度不溢出。
  • 壓縮表 (ROW_FORMAT=COMPRESSED) 下,VARCHAR 壓縮率通常高於 CHAR。
  • InnoDB 針對固定長度列有微優化(記錄頭部無長度資訊)。

總結

**CHAR 適合「短、固、頻」:短長度、固定長度、高頻更新/索引/排序。**
**VARCHAR 適合「長、變、少」:長度變化大、更新頻率低、以讀取為主。**
**鐵律:VARCHAR 定義長度 = 業務實際最大長度 + 10% 緩衝,絕不盡量設大。**

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved