極端例子:1 萬行 × 10 Bytes = 100 KB 數據,刪除 9999 行後仍佔 100 KB 空間,掃描時仍讀 100 KB。
SHOW TABLE STATUS LIKE 'table_name';
-- 關注 Data_free 列(字節),即碎片大小
SELECT
TABLE_SCHEMA AS `db`,
TABLE_NAME AS `table`,
DATA_FREE / 1024 / 1024 AS `frag_MB`,
ENGINE
FROM information_schema.TABLES
WHERE TABLE_SCHEMA NOT IN ('information_schema','mysql')
AND DATA_FREE > 0
ORDER BY DATA_FREE DESC;
| 引擎 | 命令 | 原理 | 鎖表影響 |
|---|---|---|---|
| MyISAM | OPTIMIZE TABLE tbl_name; | 整理數據文件、重建索引、回收空間 | 全程鎖表(読寫阻塞) |
| InnoDB | ALTER TABLE tbl_name ENGINE=InnoDB; | 重建表(Online DDL 5.6+ 僅元數據鎖) | 5.6+ 幾乎無鎖;5.5 鎖表 |
注意:OPTIMIZE TABLE 對 InnoDB 等同於 ANALYZE TABLE(僅更新統計),不回收空間,必須用 ALTER TABLE ... ENGINE=InnoDB。
DATA_FREE > 閾值(如 100MB 或 10% 表大小) 的表。pt-online-schema-change、gh-ost 零停機重建大表。Innodb_page_size * Innodb_pages_free 估算實例級碎片率。DATA_FREE > 100 MB 且 DATA_FREE / DATA_LENGTH > 20% → 觸發清理。定期清理碎片,讓存儲空間與掃描性能始終在線。