核心差異總覽
| 特性 | Antelope (InnoDB 基礎版) | Barracuda (Plugin 版) |
| 引入版本 | 早期內建 | InnoDB Plugin / 5.1+ |
| 支持行格式 | COMPACT, REDUNDANT | DYNAMIC, COMPRESSED |
| 長字段存儲 | < 768 字節留頁內,≥768 溢出頁 | 固定 20 字節頁內,其餘溢出頁 |
| 壓縮支持 | ❌ | ✅ (COMPRESSED) |
| 前置條件 | 無 | innodb_file_per_table=ON |
| 兼容性 | 基線 | 兼容 Antelope 表 |
行格式詳細解析
Antelope 時代
- REDUNDANT:舊格式,首部存字段長度偏移數組
- COMPACT:首部存非 NULL 變長字段長度列表,節省空間
- 變長字段 < 768 字節全部存主頁,導致頁填充率低、B+樹高度增加
Barracuda 革新
- DYNAMIC:長字段只存 20 字節指針,其餘溢出頁(類 COMPACT 但更激進)
- COMPRESSED:在 DYNAMIC 基礎上啟用頁級壓縮(zlib)
- 需同時設置:
innodb_file_format=Barracuda + innodb_file_per_table=ON
壓縮功能實戰驗證
陷阱:未設置文件格式直接建壓縮表
CREATE TABLE t1 (c1 INT PRIMARY KEY)
ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;
警告:
InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
InnoDB: ignoring KEY_BLOCK_SIZE=8.
InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_format > Antelope.
InnoDB: assuming ROW_FORMAT=COMPACT.
現象:SHOW CREATE TABLE 顯示 COMPRESSED,實際存儲為 COMPACT,**壓縮不生效**!
正確姿勢
SET GLOBAL innodb_file_per_table = 1;
SET GLOBAL innodb_file_format = Barracuda;
CREATE TABLE t3 (c1 INT PRIMARY KEY)
ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;
壓縮效果對比(540 萬行測試)
| 表 | 行格式 | .ibd 大小 | 壓縮率 |
| t1 | COMPACT (偽壓縮) | 136 MB | 基準 |
| t2 | COMPACT | 136 MB | 基準 |
| t3 | COMPRESSED | 96 MB | 29% 節省 |
關鍵參數詳解
| 參數 | 說明 | 建議值 |
| innodb_file_format | 文件格式:Antelope/Barracuda | Barracuda |
| innodb_file_per_table | 獨立表空間開關 | ON (必須) |
| ROW_FORMAT | 行格式:COMPACT/REDUNDANT/DYNAMIC/COMPRESSED | DYNAMIC (默認 5.7+) |
| KEY_BLOCK_SIZE | 壓縮頁大小:1/2/4/8/16 KB | 8K (平衡 CPU/空間) |
版本演進與默認值
- MySQL 5.5:默認 Antelope,Barracuda 需手動開啟
- MySQL 5.7:默認
innodb_file_format=Barracuda,ROW_FORMAT=DYNAMIC
- MySQL 8.0:移除 Antelope/Barracuda 概念,統一為 DYNAMIC,壓縮為獨立特性
最佳實踐建議
- ✅ 新建表默認使用
ROW_FORMAT=DYNAMIC
- ✅ 存儲 JSON、長文本、BLOB 的表評估
COMPRESSED
- ✅
KEY_BLOCK_SIZE=8K 平衡壓縮率與 CPU 開銷
- ✅ 壓縮表監控
Innodb_buffer_pool_pages_compressed 指標
- ⚠️ 壓縮表寫入性能下降 20~30%,讀取性能視解壓開銷而定
- ⚠️ 避免在高頻更新的小行表啟用壓縮
遷移指南
-- 在線修改行格式(5.6+ 支持 INPLACE)
ALTER TABLE tbl_name ROW_FORMAT=DYNAMIC;
-- 或重建表(舊版本)
CREATE TABLE tbl_new LIKE tbl_old;
ALTER TABLE tbl_new ROW_FORMAT=DYNAMIC;
INSERT INTO tbl_new SELECT * FROM tbl_old;
RENAME TABLE tbl_old TO tbl_bak, tbl_new TO tbl_old;