如何清理无用索引_mysql索引优化实践

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

清理无用索引是 MySQL 性能优化中见效快、风险低的关键操作。很多业务上线后长期未梳理索引,导致写入变慢、磁盘占用高、执行计划误判。核心思路是:先识别真正未被使用的索引,再结合查询模式和表变更频率谨慎删除。

识别无用索引的可靠方法

不能只看“没被 SELECT 用过”,还要看是否参与了 JOINORDER BYGROUP BY 或外键约束。推荐组合使用以下方式:

启用 performance_schema 并开启相关消费者(如
events_statements_history_long
table_io_waits_summary_by_index_usage
),运行一段时间后查
performance_schema.table_io_waits_summary_by_index_usage
COUNT_STAR = 0
INDEX_NAME IS NOT NULL
的索引大概率未被使用
pt-index-usage(Percona Toolkit)分析慢日志或通用日志,它会反向推导哪些索引在实际查询中从未命中 检查 information_schema.STATISTICS 中重复索引(如已有
(a,b)
,又建了
(a)
)和前缀冗余索引(如
(a(10))
(a(20))
共存)

删除前必须验证的三件事

直接 DROP INDEX 可能引发线上故障,务必确认:

该索引是否被外键引用:查
information_schema.KEY_COLUMN_USAGE
CONSTRAINT_NAME
非空则不能删
是否有应用层显式指定索引提示(USE INDEX / FORCE INDEX):grep 代码库或代理层 SQL 日志,避免删掉被强制依赖的索引 是否承担了唯一性约束或主键功能:通过
SHOW CREATE TABLE
确认索引类型,
UNIQUE KEY
PRIMARY KEY
不属于“无用”范畴

高频易误删的“伪无用”索引

有些索引看似冷门,实则关键:

仅用于 ORDER BY 或 GROUP BY 的覆盖索引:即使没出现在 WHERE 条件里,也能避免文件排序(Using filesort) 低频但高优先级的后台任务索引:如凌晨跑的报表、对账任务,不在白天流量中体现,但删除会导致超时失败 为未来字段预留的复合索引前缀:例如现有查询只用
(a)
,但索引建的是
(a,b,c)
,后续加了 b/c 过滤条件就能复用

安全清理的操作节奏

建议分阶段推进,最小化影响:

先在从库上执行
ALTER TABLE ... DROP INDEX
,观察 1–2 天复制延迟与慢查询有无突增
EXPLAIN FORMAT=TRADITIONAL
对核心接口 SQL 重做执行计划,确认删索引后没退化为全表扫描
生产环境删索引避开业务高峰,单表每次只删 1 个,间隔至少 30 分钟;大表建议用 pt-online-schema-change 在线处理

相关推荐