MySQL 大表优化
这篇是我基于一篇早期讨论内容整理的实践笔记,重点放在“遇到大表性能问题时,按什么顺序处理更稳妥”。
原讨论链接: https://www.zhihu.com/question/19719997/answer/81930332
处理顺序(先低成本,再高成本)
大多数系统都适合按以下顺序推进,避免一上来就分库分表:
- 先优化 SQL 和索引。
- 再加缓存(如 Redis),减少数据库读压力。
- 再做读写分离(主从)或副本扩展。
- 再评估分区表(前提是查询条件能命中分区键)。
- 再做垂直拆分(按业务域拆库)。
- 最后才是水平拆分(分库分表 + 路由)。
核心原因是:越往后改造成本越高,业务侵入越强,回退也越困难。
SQL 与索引是第一优先级
很多慢库问题并不是“数据库不行”,而是这三件事没有做透:
- SQL 写法没有针对索引设计。
- 索引数量过多或选择不对,拖慢写入。
- 优化单条 SQL 时忽略了全局负载,出现“局部变快、整体变慢”。
建议先做这套最小闭环:
- 用慢查询日志找 Top N SQL。
- 用
EXPLAIN验证执行计划。 - 在压测环境对比“改前/改后”整体 RT、QPS、CPU、IO。
分区、垂直拆分、水平拆分怎么选
分区表
适合“时间范围明显、查询常带分区键”的表。优点是对业务代码相对透明;缺点是分区命中差时容易扫全分区。
垂直拆分
适合按业务域解耦,把不同模块压力拆到不同库。它能降低单实例总压力,但不能解决单表本身太大的问题。
水平拆分
适合单表已达到容量或吞吐瓶颈。收益大,但代价也最大:
- 需要稳定的分片键设计。
- SQL 路由、聚合查询、跨分片事务复杂度明显上升。
- 常常需要改表结构、做冗余字段、改应用代码。
关于 InnoDB 与 MyISAM 的取舍
在当前线上系统里,绝大多数场景优先 InnoDB:
- 支持事务与行级锁。
- 并发写能力更稳。
- 故障恢复能力更好。
MyISAM 在某些纯读场景可能有优势,但在写多或读写混合场景里,通常不是优先选项。
实战建议
如果你正在处理“大表 + 写入变慢”,建议按下面清单落地:
- 先确认瓶颈在 SQL、锁、IO、还是连接池。
- 明确读写模型(读多写少、写多读少、时间范围查询比例)。
- 先完成 SQL/索引/缓存优化,再决定是否拆分。
- 如果进入拆分阶段,先做垂直拆分,再做水平拆分。