update时mysql需同步更新所有相关索引,定位、删除旧键、插入新键并维护b+树;innodb不支持disable keys,应临时删除低区分度或非关键二级索引以减少写放大。

UPDATE时索引到底干了什么
每次执行 UPDATE,MySQL 不只改数据行,还要同步维护所有涉及的索引项。比如你更新 name 字段,而该字段上有 idx_name 索引,InnoDB 就得:定位原索引叶节点 → 删除旧键值 → 插入新键值 → 更新 B+ 树结构。如果还涉及主键或唯一约束,甚至要检查冲突、加锁、回滚段写入。这些操作全在事务内完成,且无法并行——索引越多,写放大越严重。
DISABLE KEYS 只对 MyISAM 有效,InnoDB 必须换思路
很多人看到 “禁用索引提速” 就去试 ALTER TABLE ... DISABLE KEYS,但这个命令在 InnoDB 表上完全无效(会静默忽略),只对 MyISAM 生效。InnoDB 的正确做法是:临时删掉非必要二级索引,等批量更新完再重建。实测中,对一千万行表更新 200 万行,删掉 3 个低区分度的 VARCHAR 字段索引后,UPDATE 耗时从 142 秒降到 37 秒。
- 删索引前确保 WHERE 条件列仍有索引(比如主键或业务高频查询字段),否则查找阶段会退化为全表扫描
- 用
DROP INDEX idx_col ON table_name,别用DISABLE KEYS - 重建索引用
CREATE INDEX,而不是ALTER TABLE ... ENABLE KEYS
哪些索引删了最划算?看更新模式和字段区分度
不是所有索引都值得保留。以下情况删掉反而更稳更快:
一款AI开发辅助工具,主要用于使用 OpenCLI 工具,可从各类网站及桌面应用中提取数据、下载媒体内容、控制外部 CLI 工具。支持 Bilibili、知乎、小红书、Twitter/X、Reddit、YouTube、Boss直聘、即刻、微博等 30+ 个平台,以及 Cursor、Codex、ChatGPT、Notion 等桌面应用。当用户需要:从社...,适合需要提升相关任务效率的用户。
- 被更新的字段本身有索引,且该索引很少用于
WHERE或JOIN—— 比如仅用于后台报表排序,但报表跑得比更新还少 - 索引字段区分度极低(如
status TINYINT只有 0/1/2 三个值),B+ 树深度浅、选择性差,维护成本远超收益 - 复合索引里靠后的字段被频繁更新(如
INDEX idx_a_b (a,b),但你总在改b),会导致大量页分裂 - 存在冗余索引(如已有
(a,b),又单独建了(a)),删掉单列索引即可
注意:主键索引和外键约束依赖的索引不能动,否则会直接报错或破坏一致性。
真正快的关键,是让“找得到”和“写得少”不打架
索引加速的是 WHERE 定位,拖慢的是索引树更新。所以最优解从来不是“全开”或“全关”,而是:用最少、最精准的索引把目标行快速捞出来,同时砍掉所有不参与定位、纯属写负担的索引。一个容易被忽略的细节是——如果你的 UPDATE 本身走的是全表扫描(比如没加 WHERE 或条件无索引),删索引毫无意义,此时首要任务是先给 WHERE 字段建索引,而不是急着删别的。










