mysql中删除索引与性能优化

13次阅读

删除索引前必须确认其实际使用情况,否则可能导致查询变慢;需通过performance_schema或sys库视图验证,不可仅凭字段名判断,并注意主键、唯一索引及外键索引的特殊性。

mysql中删除索引与性能优化

删除索引前必须确认它是否被查询实际使用

很多团队一看到“某个索引没被创建时的字段”就直接删,结果线上 select 变慢、EXPLaiN 显示全表扫描。mysql 不会主动告诉你哪个索引正在被用——得自己查。最可靠的方式是开启 performance_schema 中的 table_io_waits_summary_by_index_usage 表(MySQL 5.6+),或用 sys.schema_unused_indexes 视图(需启用 performance_schema 并加载 sys 库)。

注意:INformatION_SCHEMA.STATISTICSSHOW INDEXES 只告诉你“有”,不告诉你“用没用”。临时禁用索引(ALTER TABLE ... DISABLE KEYS)在 InnoDB 中无效,别试。

  • 检查是否真没用:
    SELECT * FROM sys.schema_unused_indexes WHERE object_schema = 'your_db';
  • 若没开 performance_schema,至少跑一周慢查询日志 + pt-index-usage 工具分析
  • 复合索引中部分字段被查询用到(比如 (a,b,c) 上只查 a = ?),该索引仍算“被使用”,不能仅因 c 没出现就删

DROP INDEX 语句本身会锁表(InnoDB 下取决于 MySQL 版本)

MySQL 5.6 之前,DROP INDEX 会触发表重建,整个过程阻塞 DML;5.7+ 支持 ALgoRITHM=INPLACE 的在线 DDL,但仍有条件限制:索引不是主键、不涉及全文/空间索引、且表引擎为 InnoDB。

执行前务必确认版本和存储引擎,否则可能在高峰期卡住业务写入。

  • 安全写法(显式指定算法):
    ALTER TABLE t1 DROP INDEX idx_name, ALGORITHM=INPLACE, LOCK=NONE;
  • 若报错 ALGORITHM=INPLACE is not supported,说明不满足条件,得切到低峰期用 ALGORITHM=copy(会锁表)
  • 主键索引不能用 DROP INDEX 删除,必须用 ALTER TABLE ... DROP PRIMARY KEY,且会重建聚簇索引,代价极高

删除索引后写入变快,但某些查询可能陡然变慢

索引本质是“以空间换时间”的冗余结构。删掉一个索引,INSERT/UPDATE/delete 的维护开销下降,但原本走索引的 WHEREORDER BYJOIN 可能退化为文件排序或临时表,CPU 和 I/O 压力反而上升。

尤其要注意覆盖索引场景:如果一个 SELECT a,b FROM t WHERE c=? 原本命中 (c,a,b) 覆盖索引,删掉后变成回表+排序,延迟可能翻几倍。

  • 删索引前,用 EXPLAIN FORMAT=jsON 对核心 SQL 重跑执行计划,比对 keyrowsextra 字段变化
  • 监控删索引后 Handler_read_rnd_next(随机读行数)和 Sort_merge_passes 是否激增
  • 批量导入场景下,可临时删非关键索引加速写入,但导入完必须立刻重建——别忘了

唯一索引与外键约束不能随便删

唯一索引(含主键)不只是性能结构,更是数据完整性保障。删掉唯一索引后,应用层插入重复值不会报错,直到唯一约束失效引发脏数据;外键索引被删会导致 ALTER TABLE ... DROP FOREIGN KEY 失败,因为 MySQL 要求外键字段必须有索引支撑。

这类索引哪怕“看起来没被查询用”,也不能按普通索引处理。

  • 检查是否为外键索引:
    SELECT CONSTRAINT_NAME, COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_SCHEMA = 'db' AND TABLE_NAME = 't' AND REFERENCED_TABLE_NAME IS NOT NULL;
  • 检查是否为唯一约束:SHOW CREATE TABLE t 中找 UNIQUE KEYPRIMARY KEY
  • 真要删,必须同步评估业务逻辑能否容忍重复、级联操作是否可控、下游服务是否依赖该约束语义

真正难的不是语法怎么写,是判断“这个索引到底是不是冗余”——它可能在某个凌晨三点的报表任务里悄悄扛着压力,也可能在某个未覆盖的异常分支里唯一生效。删之前,看数据,看执行计划,看监控曲线,别信名字,也别信直觉。

text=ZqhQzanResources