不能仅凭performance_schema.table_io_waits_summary_by_index_usage中COUNT_READ=0就删除索引,因其不记录ORDER BY、外键、FORCE INDEX及低频后台任务依赖,误删将导致查询变慢十倍或DDL失败。

不能只看 performance_schema.table_io_waits_summary_by_index_usage 里 COUNT_READ = 0 就删索引——它不记录 ORDER BY、外键、FORCE INDEX 或低频后台任务的依赖,误删会导致查询变慢十倍甚至 DDL 失败。
确认 performance_schema 索引统计是否真在工作
这个视图默认常是关闭的,查出来全是 0 不代表索引没用过,只代表没统计。必须分三步验证:
- 检查是否启用:
SELECT VARIABLE_VALUE FROM performance_schema.global_variables WHERE VARIABLE_NAME = 'performance_schema';,结果必须是ON - 启用消费者:
UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME IN ('events_waits_current', 'events_statements_history_long'); - 启用采集器:
UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' WHERE NAME LIKE 'wait/io/table/%';
做完这三步,再等至少 24 小时(覆盖完整业务周期),才可查该视图。否则所有 COUNT_READ = 0 都不可信。
用 EXPLAIN FORMAT=TRADITIONAL 验证真实查询路径
很多索引不参与 WHERE 过滤,但支撑排序、分组或覆盖扫描。仅看 key 字段会漏掉关键依赖:
- 盯
Extra字段:Using index表示走了覆盖索引;Using filesort消失可能正依赖该索引 - 特别注意无
WHERE的语句,例如:SELECT id, name FROM users ORDER BY created_at LIMIT 10——即使COUNT_READ = 0,删掉(created_at)会强制全表扫描 +filesort - 带
OR、IN或函数的语句(如WHERE DATE(created_at) = '2026-06-01')容易绕过索引,但不等于索引无用
识别冗余索引:不是字段重复,而是前缀完全覆盖
冗余指功能重叠、可被其他索引完全替代。比如 INDEX(a) 和 INDEX(a, b) 共存时前者冗余,但 INDEX(a, b) 和 INDEX(a, c) 并不冗余——因为 b 和 c 不同,无法互相替代:
- 用
SELECT table_name, index_name, seq_in_index, column_name FROM information_schema.statistics WHERE table_schema = 'your_db' ORDER BY table_name, index_name, seq_in_index;查字段顺序 - 对每个表,按
index_name分组,手动比对是否有前缀完全一致的索引(如idx_user_id和idx_user_id_status) -
INDEX(user_id, status)存在时,再建INDEX(user_id)就是冗余的——后者能做的事,前者全都能做
删之前必须交叉验证的三件事
光看一个视图就动手,等于蒙眼拆保险丝:
- 查外键依赖:
SELECT CONSTRAINT_NAME, COLUMN_NAME FROM information_schema.KEY_COLUMN_USAGE WHERE TABLE_SCHEMA = 'db_name' AND TABLE_NAME = 'tbl_name' AND CONSTRAINT_NAME != 'PRIMARY' AND REFERENCED_TABLE_NAME IS NOT NULL;,有结果就不能删 - 搜代码和代理日志:
grep -r "FORCE INDEX\|USE INDEX" ./src/,避免应用层硬编码索引名 - 确认是否承担唯一性约束:
SHOW CREATE TABLE tbl_name中看该索引是否为UNIQUE KEY或PRIMARY KEY——这类索引不属于“无用”范畴
最易被忽略的是低频但高优先级的后台任务索引,比如凌晨跑的对账 SQL,不在白天流量中体现,但删除会导致超时失败。真正安全的清理,永远建立在对查询模式的真实理解之上,而不是统计数字的表面清零。


















