| 維度 | MyISAM | InnoDB |
|---|---|---|
| 儲存結構 | 三檔:.frm(結構) .MYD(資料) .MYI(索引) | 共享表空間 ibdata1 或獨立 .ibd (file-per-table) |
| 鎖粒度 | 表鎖 | 行鎖 (支援 MVCC) |
| 事務支援 | 無 | ACID 完整支援 |
| 外鍵 | 不支援 | 支援 |
| 全文索引 | 內建 (5.6+) | 5.6+ 內建,較早版本需 Sphinx |
| 崩潰恢復 | 需 REPAIR TABLE,慢、可能遺失資料 | Redo/Undo Log 自動恢復,秒級完成 |
COUNT(*) 效能 | O(1) 直接讀取計數器 | O(N) 全表掃描 (無 WHERE) |
| 主鍵查詢 | 需走 .MYI 索引檔 | 聚簇索引直接定位,極快 |
| 大量 INSERT | 較快 (延遲寫入) | 稍慢 (WAL 機制) |
| 高併發 UPDATE | 表鎖阻塞嚴重 | 行鎖並發優異 |
innodb_buffer_pool_size 同時緩存資料與索引,MyISAM 僅緩存索引 (.MYI),資料仰賴 OS page cache,雙層管理效率較低。
非唯一二級索引的插入/刪除/更新可先寫入 change buffer,稍後背景合併,大幅降低隨機 I/O。
熱點頁面自動建立雜湊索引,等價查詢接近 O(1)。
| 誤區 | 事實 |
|---|---|
| InnoDB 不支援全文索引 | 5.6+ 完整支援,且支援中文分詞 (ngram parser) |
SELECT COUNT(*) 在 InnoDB 永遠慢 | 加 WHERE 條件後兩者相同;可用觸發器維護計數表或 INFORMATION_SCHEMA.TABLES.TABLE_ROWS 估算值 |
| InnoDB 表鎖只有行鎖 | 無法確定掃描範圍時 (如 WHERE name LIKE '%abc%') 仍會升級為表鎖 |
MyISAM 壓縮表 (myisampack) 省空間 | 唯讀、無法修改,InnoDB 可用 ROW_FORMAT=COMPRESSED 同樣壓縮且可寫入 |
-- 1. 停寫入或低峰期
ALTER TABLE big_table ENGINE=InnoDB;
-- 2. 大表分批遷移 (pt-online-schema-change)
pt-online-schema-change --alter "ENGINE=InnoDB" D=db,t=big_table --execute
-- 3. 調整參數
innodb_buffer_pool_size = 物理記憶體 70%
innodb_log_file_size = 1G
innodb_flush_log_at_trx_commit = 1
innodb_file_per_table = ON
現代 MySQL (5.7/8.0) 預設且強烈推薦 InnoDB。除非極特殊的唯讀、全文搜尋、嵌入式場景,MyISAM 已無優勢。新專案直接用 InnoDB,舊專案規劃遷移路線圖。