mysql如何管理索引的生命周期_mysql索引维护指南

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

什么时候该删掉一个索引

索引不是越多越好,冗余或低效的索引会拖慢写入、占用磁盘、增加优化器决策负担。判断要不要删,核心看两点:有没有被用到,以及是否和其他索引重复。

先查

information_schema.statistics
或用
SHOW INDEX FROM table_name
看索引定义;再结合
performance_schema.table_io_waits_summary_by_index_usage
(MySQL 8.0+)确认实际命中次数——长期
COUNT_STAR = 0
的索引基本可以标记为待清理。

复合索引
INDEX (a, b)
和单独索引
INDEX (a)
共存时,后者大概率冗余(除非有
WHERE a = ? ORDER BY b DESC
这类需要单独排序的场景)
ALTER TABLE ... DROP INDEX
不锁表(Online DDL),但大表仍建议在低峰期执行
删除前用
EXPLAIN SELECT ...
对比关键查询的执行计划,防止误伤

如何安全地重建低效索引

索引碎片化、统计信息过期、页分裂严重时,

SELECT
性能会下降,但直接
DROP + CREATE
有风险:中间空窗期查询可能走全表扫描,且大索引重建过程阻塞写入(尤其 MySQL 5.7 及更早版本)。

优先用
OPTIMIZE TABLE table_name
(InnoDB 下本质是重建表 + 索引,需额外磁盘空间)
MySQL 5.6+ 支持
ALTER TABLE ... ALGORITHM=INPLACE, LOCK=NONE
重建单个索引,例如:
ALTER TABLE t1 DROP INDEX idx_a, ADD INDEX idx_a (a) ALGORITHM=INPLACE
重建后务必执行
ANALYZE TABLE table_name
,否则优化器可能继续用旧的统计信息做错误判断

哪些操作会意外让索引失效

不是 SQL 写错才失效,很多看似合理的写法在底层无法走索引,比如隐式类型转换、函数包裹字段、模糊查询左匹配等。

WHERE phone = 13800138000
(phone 是 VARCHAR)→ 触发隐式转换,索引失效
WHERE DATE(create_time) = '2024-01-01'
→ 函数作用于索引列,无法使用索引
WHERE name LIKE '%abc'
→ 左模糊,B+Tree 无法从头定位
WHERE status IN (1,2,3) AND create_time > '2024-01-01'
→ 如果复合索引是
(create_time, status)
,顺序反了也用不上

监控索引使用情况的最小可行方案

不依赖外部工具,只用 MySQL 自带能力就能快速摸清索引真实价值。重点不是“有没有”,而是“谁在用、怎么用、用了多少次”。

MySQL 8.0+:查
performance_schema.table_io_waits_summary_by_index_usage
,关注
COUNT_READ
字段,值为 0 且存在超过一周可预警
所有版本:开启慢查询日志 +
log_queries_not_using_indexes = ON
,但注意它只记录“完全没走索引”的语句,对部分走索引的无效查询无感知
定期跑
SELECT * FROM sys.schema_unused_indexes
(sys schema 需要初始化),它基于 performance_schema 数据聚合,比手写 SQL 更准

真正麻烦的不是建错索引,而是没人定期看它还活不活着。索引没有自动退休机制,得靠人盯住那些半年没被

SELECT
触碰过的
INDEX
名字。

相关推荐