mysql如何检查和重建索引_mysql索引碎片优化

来源:这里教程网 时间:2026-02-28 20:46:58 作者:

怎么查 MySQL 表的索引碎片率

MySQL 本身不直接暴露“碎片率”数值,但可以通过

INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
INFORMATION_SCHEMA.INNODB_SYS_INDEXES
配合估算。更实用的是查
DATA_FREE
和页利用率:

对 InnoDB 表,执行
SHOW TABLE STATUS LIKE 'your_table_name'
,关注
Data_free
字段(单位字节)——它表示已分配但未使用的空间,值越大越可能有碎片
SELECT table_name, round(((data_length + index_length) / 1024 / 1024), 2) AS size_mb, round((data_free / 1024 / 1024), 2) AS free_mb FROM information_schema.tables WHERE table_schema = 'your_db' AND table_name = 'your_table';
free_mb
超过
size_mb
的 20%~30%,且表长期有大量 DELETE/UPDATE,就值得优化

OPTIMIZE TABLE 能不能重建索引

对 InnoDB 表,

OPTIMIZE TABLE
实际上等价于
ALTER TABLE ... FORCE
(MySQL 5.6+),会重建整个表并重新组织聚簇索引和二级索引,同时更新统计信息。

它会锁表(在可重复读隔离级别下是 ALGORITHM=COPY,全表拷贝;8.0+ 支持 INPLACE,但仍需排他 MDL 锁) 不适用于只读从库或高负载主库,容易触发超时或阻塞写入 执行后
Data_free
通常归零或显著下降,但不会改变索引结构逻辑(比如不会合并单列索引为联合索引)

ALTER TABLE ... REBUILD 和 ANALYZE TABLE 的区别

ALTER TABLE t REBUILD
(MySQL 8.0.23+)仅重组织物理存储,不重建索引定义;而
ANALYZE TABLE
只更新索引统计信息(用于优化器选执行计划),完全不碰数据页。

REBUILD
是轻量级操作,不锁 DML(支持并发 INSERT/UPDATE/DELETE),适合在线整理碎片
ANALYZE TABLE
几乎无开销,但对碎片无效——它解决的是“优化器误判”,不是“磁盘空间浪费”
如果只是查询变慢且
EXPLAIN
显示走了错误索引,先试
ANALYZE TABLE
;如果
Data_free
大且
SELECT COUNT(*)
响应明显变慢,再考虑
REBUILD
OPTIMIZE

重建索引时最容易忽略的点

真正影响效果的不是命令本身,而是上下文约束:

唯一索引或主键被外键引用时,
OPTIMIZE TABLE
仍能执行,但某些版本会跳过外键检查导致后续插入失败——务必提前
SHOW CREATE TABLE
确认外键定义
使用压缩表(
ROW_FORMAT=COMPRESSED
)时,
OPTIMIZE
可能因页大小不匹配失败,报错
Failed to allocate page
,此时需显式指定
KEY_BLOCK_SIZE
如果表启用了加密(
ENCRYPTION='Y'
),
REBUILD
不会改变加密状态,但
OPTIMIZE
在某些版本中会临时解密再重加密,延长执行时间

碎片不是越小越好——过度优化反而增加 I/O 和锁争用。观察一周内

Data_free
的增长趋势,比单次清理更重要。

相关推荐