為什麼需要 OPTIMIZE TABLE?
大量 DELETE、UPDATE 可變長度列(VARCHAR/BLOB/TEXT)後,資料檔案會產生碎片,檔案大小不減反增,讀寫效能下降。Discuz! 等系統內建「資料表優化」功能即呼叫此命令。
語法
OPTIMIZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name] ...;
LOCAL / NO_WRITE_TO_BINLOG:不寫入二進位日誌,不複寫到從庫。
運作原理
- 建立原表的臨時副本。
- 將資料重新整理寫入副本(重建索引、壓縮碎片)。
- 原子替換原表。
全程鎖表,大表操作時間較長,建議低峰期執行。
引擎別行為差異
| 引擎 | 實際動作 |
| MyISAM | 修復表 → 排序索引頁 → 更新統計資訊 |
| InnoDB | 映射為 ALTER TABLE ... ENGINE=InnoDB 重建表,更新索引統計、釋放叢集索引空間 |
| BDB (已棄用) | 映射為 ANALYZE TABLE |
適用場景
- 刪除大量資料後。
- 頻繁更新可變長度列(VARCHAR/BLOB/TEXT)的表。
- 定期維護:每週/每月一次,僅針對碎片嚴重表。
- 不需 對唯讀、固定長度、少量變動的表頻繁執行。
碎片檢測:判斷是否需要優化
SELECT
TABLE_NAME,
DATA_LENGTH,
INDEX_LENGTH,
DATA_FREE,
ROUND(DATA_FREE / (DATA_LENGTH + INDEX_LENGTH) * 100, 2) AS frag_pct
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'your_db'
AND DATA_FREE > 0
ORDER BY frag_pct DESC;
frag_pct > 20% 建議排程優化。
線上優化替代方案(減少鎖表影響)
- pt-online-schema-change (Percona Toolkit):觸發器+臨時表,近零停機重建。
- gh-ost (GitHub):無觸發器,基於 binlog 同步,更安全。
- MySQL 8.0+
ALTER TABLE ... ALGORITHM=INPLACE, LOCK=NONE 部分操作支援線上。
複寫注意事項
預設寫入 binlog 並複寫到從庫。大表優化會導致從庫同步延遲。跨機房複寫建議加 NO_WRITE_TO_BINLOG,改由人工在從庫各自執行。
總結檢查清單
- 確認表引擎支援(MyISAM/InnoDB)。
- 檢測碎片率 > 20%。
- 選擇低峰期,預估鎖表時間(大表可用線上工具)。
- 決定是否複寫(
NO_WRITE_TO_BINLOG)。
- 執行
OPTIMIZE TABLE 或線上替代方案。
- 驗證
DATA_FREE 歸零、檔案縮小、查詢效能提升。
- 上一篇文章: MySQL 自定義函數與存儲過程完整開發指南
- 下一篇文章: MySQL 顯示表資訊完整指令大全:SHOW 系列與 mysqlshow
Copyright ©
程式碼之家 All Rights Reserved