大量刪除/更新操作會導致數據頁面分裂、空洞,產生「數據碎片」,嚴重影響掃描性能、佔用額外磁盤空間。本文深度解析碎片成因、檢測指標、MyISAM 與 InnoDB 的整理差異。
碎片分兩類:單行碎片(行內空洞)與 多行碎片(頁面間邏輯順序與物理順序不一致)。索引同樣產生碎片。
DATA_FREE-- 查看所有表碎片空間(字節)
SELECT TABLE_SCHEMA, TABLE_NAME, DATA_FREE
FROM information_schema.TABLES
WHERE TABLE_SCHEMA NOT IN ('mysql','information_schema','performance_schema','sys')
AND DATA_FREE > 0
ORDER BY DATA_FREE DESC;
-- 單表詳情
SHOW TABLE STATUS FROM db_name LIKE 'table_name'\G
-- 關注:Data_free、Avg_row_length、Row_format
DATA_FREE > 0 表示存在可重用空間(碎片)DATA_FREE 反映整個表空間碎片,非單表OPTIMIZE TABLEOPTIMIZE TABLE `table_name`;
原理:重建表(臨時表拷貝數據 → 替換原表),物理順序重組,索引重建,釋放碎片空間。
特點:
建議:低峰期執行,配合 myisamchk -r 離線更快。
InnoDB 不支持 傳統 OPTIMIZE TABLE(實際執行 ALTER TABLE ... ENGINE=InnoDB)。
ALTER TABLE tbl ENGINE=InnoDB(5.6+ Online DDL)ALTER TABLE `large_table` ENGINE=InnoDB;
tmpdir)OPTIMIZE TABLE(實際同方案 1)InnoDB 表執行 OPTIMIZE TABLE 等價於 ALTER TABLE ... ENGINE=InnoDB + ANALYZE TABLE。
pt-online-schema-change(零停機、可控)pt-online-schema-change \ --alter "ENGINE=InnoDB" \ D=db_name,t=table_name \ --execute \ --max-load Threads_running=50 \ --critical-load Threads_running=100
-- 1. 創建表並插入 4 行
CREATE DATABASE xinxing;
USE xinxing;
CREATE TABLE xin (c CHAR(40)) ENGINE=MyISAM;
INSERT INTO xin VALUES ('xiaohei'),('xiaoqian'),('xiaolin'),('xiaonan');
-- 2. 查看:Data_free = 0
SHOW TABLE STATUS FROM xinxing LIKE 'xin'\G
-- 3. 刪除 1 行
DELETE FROM xin WHERE c = 'xiaolin';
-- 4. 再查:Data_free = 121(產生碎片)
SHOW TABLE STATUS FROM xinxing LIKE 'xin'\G
-- 5. 整理
OPTIMIZE TABLE xin;
-- Data_free 歸 0
OPTIMIZE TABLE / ALTER TABLE ENGINE=InnoDB 會重建所有索引,消除索引碎片,恢復 B+ 樹填充度。
| 引擎 | 整理命令 | 是否鎖表 | 推薦工具 | 頻率 |
|---|---|---|---|---|
| MyISAM | OPTIMIZE TABLE | 是(表鎖) | myisamchk -r (離線) | 週/月,低峰期 |
| InnoDB | ALTER TABLE ENGINE=InnoDB | Online DDL(短暫 MDL) | pt-online-schema-change | 月/季,配合監控 DATA_FREE |
建立 DATA_FREE 監控告警(如 > 表大小 20%),定期低峰整理,保持存儲緊湊、掃描高效。