最准、最轻量的MyISAM碎片检测方式是直接查information_schema.TABLES中DATA_FREE是否显著大于0,并结合DATA_LENGTH和TABLE_ROWS判断;DATA_FREE>0即存在碎片,超DATA_LENGTH的10%~20%建议OPTIMIZE。

直接看 Data_free 值是否显著大于 0,再结合 Rows 和 Data_length 判断碎片程度——这是最准、最轻量的检测方式。
查 information_schema.TABLES 获取真实碎片量
MyISAM 表的碎片不会自动暴露在日常查询里,必须主动查元数据。执行:
SELECT TABLE_NAME, ENGINE, DATA_LENGTH, DATA_FREE, TABLE_ROWS FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'your_db' AND ENGINE = 'MyISAM';
关键看三列:
-
DATA_FREE> 0 是明确信号:表示有未被复用的空闲空间(即“碎片”);若超过DATA_LENGTH的 10%~20%,基本该优化了 -
TABLE_ROWS明显不准确(比如远低于实际行数),说明统计信息陈旧,OPTIMIZE TABLE会顺带更新它 -
DATA_LENGTH比导入前或上次优化后明显膨胀,但业务写入量没变,大概率是碎片堆积
别信 CHECK TABLE 的返回结果
CHECK TABLE 只告诉你表“是否损坏”,不反映碎片状态。它返回 status: OK 时,表可能完全健康,但 DATA_FREE 已高达几十 MB —— 这种情况很常见,尤其在频繁 DELETE 或 UPDATE 变长字段(如 VARCHAR、TEXT)之后。
真正要警惕的是这些组合:
-
CHECK TABLE tbl_name返回OK,但DATA_FREE / DATA_LENGTH > 0.15 -
SHOW TABLE STATUS LIKE 'tbl_name'中Rows为NULL或明显偏低(MyISAM 不维护实时行数,靠采样估算) - 执行
SELECT COUNT(*)后发现和Rows相差 2 倍以上
避免用 myisamchk -s 做常规检测
myisamchk -s 需要停止 MySQL 或锁表,对线上 MyISAM 表风险高,仅适合离线巡检。它输出的 “warning: 1 client is using or hasn’t closed the table properly” 并不等于需要 OPTIMIZE,只是提示表曾异常关闭——此时应先 REPAIR TABLE,而非直接优化。
更实用的做法是定期跑这个轻量 SQL:
SELECT TABLE_NAME, ROUND(DATA_FREE / DATA_LENGTH * 100, 2) AS free_pct, DATA_FREE, DATA_LENGTH FROM information_schema.TABLES WHERE ENGINE = 'MyISAM' AND DATA_FREE > 1024*1024 -- 只关注 1MB 以上的碎片 ORDER BY free_pct DESC;
只要 free_pct 超过 10%,且表是高频读写的,就值得安排 OPTIMIZE TABLE。
真正容易被忽略的是:MyISAM 的 OPTIMIZE TABLE 会重建整个 .MYD 和 .MYI 文件,期间表不可写,且临时空间需 ≥ DATA_LENGTH + INDEX_LENGTH。别在磁盘只剩 20% 时才想起来检查 DATA_FREE。


















