mysql如何重建索引_mysql索引维护方法

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

ALTER TABLE ... ENGINE=InnoDB 会重建所有索引

对 InnoDB 表执行

ALTER TABLE t ENGINE=InnoDB
(即使引擎没变),MySQL 会重建整张表,包括所有二级索引和聚簇索引。这是最彻底的“重建索引”方式,能消除页分裂、释放碎片空间、重排 B+ 树结构。

但要注意:该操作会加

SX
(共享读写)锁,阻塞 DML(INSERT/UPDATE/DELETE),且耗时与表大小正相关。线上大表慎用,建议在低峰期配合
pt-online-schema-change
或 MySQL 8.0+ 的
ALGORITHM=INPLACE
可选参数控制。

MySQL 5.6+ 支持部分
ALTER
操作为
INPLACE
,例如
ADD INDEX
DROP INDEX
不触发全表重建
OPTIMIZE TABLE t
在 InnoDB 中等价于
ALTER TABLE t ENGINE=InnoDB
,效果相同
MyISAM 表上
OPTIMIZE TABLE
才真正“整理碎片”,InnoDB 下它只是重建

DROP INDEX + CREATE INDEX 是最可控的单索引重建方式

如果只怀疑某个二级索引损坏或严重膨胀(比如

cardinality
明显偏低、
data_length
异常高),直接删掉再建更轻量、影响更小。

执行前先确认索引名:

SHOW INDEX FROM t;
然后执行:

DROP INDEX idx_name ON t;
CREATE INDEX idx_name ON t (col1, col2);

注意点:

MySQL 5.7+ 默认允许并发 DML,但
DROP INDEX
仍需短暂元数据锁(MDL),一般毫秒级
重建过程中,该索引不可用,查询若强制走这个索引会报错
Unknown index
务必核对
CREATE INDEX
的列顺序、排序方向(
ASC
/
DESC
)、前缀长度(如
name(10)
),否则语义可能改变

使用 ANALYZE TABLE 更新索引统计信息,不重建但影响查询计划

索引本身没坏,但优化器选错了执行路径?大概率是统计信息过期。

ANALYZE TABLE
不重建索引,只采样页并更新
information_schema.STATISTICS
中的
cardinality
值。

它快(毫秒级)、无锁(只读锁),适合日常维护:

ANALYZE TABLE t;

常见触发场景:

表数据量突增 > 10% 且未做
ANALYZE
EXPLAIN
显示用了错误索引,而
SHOW INDEX
查到该索引
Cardinality
为 1 或远低于实际唯一值数量
升级 MySQL 版本后首次运行查询,旧统计信息不兼容新优化器逻辑

误删索引后恢复:靠备份或 SHOW CREATE TABLE

手抖执行了

DROP INDEX
又没记下定义?别急着 panic。

如果表结构没变过,

SHOW CREATE TABLE t
能还原当前所有索引定义(包括隐式主键);如果已改过结构,且没有逻辑备份(如
mysqldump --no-data
),就只能从最近一次备份里提取
CREATE INDEX
语句。

关键提醒:

MySQL 不记录索引创建时间,
information_schema
里查不到历史 DDL
binlog 是行格式(ROW)时,不包含索引变更事件;只有 STATEMENT 格式才可能在日志里看到
DROP/CREATE INDEX
,但不可靠
生产库建议定期导出
SHOW CREATE TABLE
结果存档,比依赖记忆靠谱得多
重建索引不是“定期跑个脚本”就能解决的事——得看是物理碎片、统计失真,还是索引定义错误。三者对应的操作成本、风险、验证方式完全不同。动手前先用
SHOW INDEX
EXPLAIN
定位真实瓶颈,比盲目
OPTIMIZE
有用得多。

相关推荐