MySQL 大表优化
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/索引/缓存优化,再决定是否拆分。 如果进入拆分阶段,先做垂直拆分,再做水平拆分。 延伸阅读 MySQL 宽表写入性能问题:为什么会慢,何时该考虑时序库 数据库水平拆分垂直拆分 MySQL INNODB