Yihui’s Blog

MySQL 一亿条数据,怎么快速加索引?

日期:2026-07-12
标签:#面试 #八股 #后端 #MySQL #索引 #场景题

一句话答案

先确认版本与 DDL 算法,在影子/从库验证时间和空间;优先使用支持的 Online DDL,重型场景用 gh-ost/pt-osc 或新表重建切换,并限速、监控复制与元数据锁。

面试口语版

一亿行加索引本质要扫描和排序大量数据,不可能零成本。先用同版本、同量级数据评估索引大小、临时空间和构建时间,清理长事务并确认是否支持 ALGORITHM=INPLACE、LOCK=NONE 等在线能力。执行时低峰限速,监控 CPU、I/O、redo/undo、磁盘、主从延迟和 MDL 等待。若原生 DDL 影响不可接受,可用 gh-ost/pt-online-schema-change 创建带索引影子表、复制全量、同步增量后原子切换;也可先在从库建索引再切换角色,但需规划复制拓扑和回滚。

关键细节

  • Online DDL 不等于无锁或无性能影响,开始/结束仍可能获取元数据锁。
  • 预留原表、索引、临时文件和 binlog 的足够磁盘空间。
  • 先确认索引确有收益,避免构建低选择性或重复索引。
  • 唯一索引还需提前扫描重复数据,切换期间防新增冲突。

面试官追问

  1. 为什么在线加索引仍可能阻塞业务?
  2. gh-ost 的核心原理是什么?
  3. 如何验证新索引有效且没有副作用?

面试官追问参考答案

1. 为什么在线加索引仍可能阻塞业务?

DDL 开始和提交阶段仍需 Metadata Lock,长事务会让它等待并可能使后续查询排队;构建过程还会争抢 I/O、CPU、Buffer Pool 和复制带宽,业务延迟可能升高。

2. gh-ost 的核心原理是什么?

创建包含新索引的影子表,按块复制旧数据,同时解析 binlog 将增量变更应用到影子表;追平后短暂获取锁并原子交换表名。失败前原表仍在,便于终止和回滚。

3. 如何验证新索引有效且没有副作用?

用真实参数执行 EXPLAIN ANALYZE,对比扫描行数、回表、P99 和总资源;灰度观察写延迟、索引空间、Buffer Pool 命中及复制延迟。确认无冗余索引后再清理旧索引。

学习清单

  • 理解在线 DDL、MDL 和影子表迁移。
  • 能规划空间、监控和回滚。
Maintained by · YihuiEdit on GitHub

Keep reading

View all posts