You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

MySQL添加复合索引并删除旧索引的最佳实践及单语句安全性咨询

问题解答

1. 单条SQL语句能否完成操作?

可以,且完全符合你的需求。

MySQL在处理单条ALTER TABLE包含多个操作时,会优先执行所有ADD INDEX类的添加操作,待新索引创建完成后,再执行DROP INDEX类的删除操作,不会出现先删旧索引、表临时无索引的状态。

同时,单条ALTER TABLE是原子操作:要么所有操作执行成功,要么全部回滚,不会出现半完成的中间状态,保障数据一致性。

你提供的SQL语句是可行的:

ALTER TABLE my_table
    ADD INDEX idx_c1_c2 (c1, c2),
    DROP INDEX idx_c1;

2. 低性能开销的推荐方案

优先使用单条原子ALTER语句

对于MySQL 5.6及以上版本的InnoDB表(数据量较大但未到TB级),这种方式开销最低:

  • InnoDB支持在线DDL,添加/删除索引过程中,仅在最后同步元数据阶段有短暂锁表,业务可正常读写。
  • 单条语句仅需一次表数据扫描(创建复合索引时),比分开执行两条ALTER的开销更小(两条语句会扫描两次表)。

超大规模表的优化方案

如果是TB级超大表,即使在线DDL也可能带来明显负载,可采用:

  • 使用第三方在线DDL工具:如Percona的pt-online-schema-change或GitHub的gh-ost,通过复制表数据、同步增量变更的方式完成索引修改,全程无锁表,对业务影响极小。
  • 选择业务低峰期执行:避开流量高峰,降低对用户体验的影响。
  • 提前监控系统负载:执行前确认CPU、磁盘IO、内存有足够余量支撑DDL操作。

额外注意事项

  • 复合索引(c1,c2)的前缀列是c1,所有原本依赖单列索引idx_c1的查询,都可通过新复合索引完成,删除旧索引不会影响这类查询的性能。
  • 若MySQL版本低于5.6,InnoDB的ALTER TABLE会锁表,建议使用第三方工具避免长时间锁表。

内容的提问来源于stack exchange,提问作者Jacky Wang

火山引擎 最新活动