接手一张老表,索引建了五六个,写入越来越慢,排查发现一半是重复的。mysql 删除索引的语法很固定,两种写法效果一样:
DROP INDEX idx_name ON user_order;ALTER TABLE user_order DROP INDEX idx_name;把 idx_name 换成自己的索引名。两种写法随习惯选,用 Navicat、DataGrip 这类图形工具在索引上右键删除,背后执行的也是这两条。删之前先看清名字,别把正在用的删了:
SHOW INDEX FROM user_order;结果里 Key_name 一列就是索引名;同一个名字出现多行说明是联合索引,Seq_in_index 能看出覆盖了哪几个字段。拿不准建表语句的话,SHOW CREATE TABLE user_order; 里也能看到全部索引定义,想保存一份留底也方便。
主键和唯一索引的删法
主键不叫删除索引,写法单独一套:
ALTER TABLE user_order DROP PRIMARY KEY;唯一索引跟普通索引一样用 DROP INDEX 删。要是这个索引被外键引用着,多数情况会报 1553 错误,得先把外键约束去掉再删索引。
大表删除前想三件事
- 删索引是 DDL 操作,MySQL 5.6 之后的 InnoDB 大多支持在线执行,但表特别大时照样占 IO,挑业务低峰做。
- 动手前用 EXPLAIN 确认没有查询依赖它。有的索引看着重复,其实是覆盖索引,删了关键查询直接走全表扫描。
- 几千万行的大表,先在测试库演练一遍,或者用 pt-online-schema-change 这类在线变更工具,别直接在生产表上赌运气。
- 删除前把表结构和索引用 SHOW CREATE TABLE 存一份,万一删错还能按原文加回来,恢复路径先想好。
判断标准很简单:写多读少的表,索引越精越好,删完观察一天慢查询日志,写入耗时明显下降就删对了。mysql 删除索引本身是秒级的事,风险全在删错对象上,执行前把索引名核对清楚,比任何操作技巧都重要。顺带一提,同一张表的 DDL 是排队执行的,大表加索引和删索引别挤在一起做。