分库分表是最后手段,非数据量超2000万行、单表.ibd超50gb、qps长期超8000、锁等待超50ms且sql无法索引优化时不应轻易实施,须优先考虑分区、冷热分离、mysql 8.0升级等替代方案。

别急着拆,先看单表是否真到了非拆不可的地步——多数情况下,分库分表是最后手段,不是性能优化的第一步。
单表行数和文件大小是否突破临界值?
这两个指标最直观,但不能孤立看:
- 单表行数超
2000万行,且持续增长,B+树层高大概率已从3层升到4层,一次查询多一次磁盘IO(1–10ms),尤其在Buffer Pool无法覆盖热数据时,延迟感知明显 - 单表.ibd文件超过
50GB(SSD环境可放宽至100GB),ALTER TABLE操作开始卡顿,OPTIMIZE TABLE几乎不可用,备份窗口拉长,主从同步延迟风险陡增 - 注意:如果表里大量是历史归档数据(如3年前订单),优先考虑分区表(
PARTITION BY RANGE)或冷热分离,而不是直接分库分表
QPS和连接数是否持续打满单实例?
这是判断“该分库”而非“该分表”的关键:
- 读写混合QPS长期稳定在
8000+,或纯写QPS超3000,SHOW STATUS LIKE 'Threads_connected'经常接近max_connections设置值(默认151,实际生产建议设为1000左右) - 出现
Too many connections错误,或应用层数据库连接池频繁报Connection timeout - 监控中
Innodb_row_lock_time_avg>50ms、事务冲突率(innodb_deadlocks增速)明显上升,说明不是数据量问题,而是资源争用——这时水平分库比水平分表更对症
SQL执行是否已无法靠索引和改写优化?
很多团队跳过这步就上分库分表,结果新架构跑着慢SQL,反而更难排查:
- 用
EXPLAIN FORMAT=JSON看执行计划,确认是否已用上覆盖索引、是否扫描行数远超返回行数(rows_examined / rows_sent > 100) - 是否存在无法避免的跨分片查询场景,比如业务强依赖
ORDER BY created_at LIMIT 20,但分片键是user_id——这种查询在分库分表后会变成N次查询+内存合并,延迟可能翻倍 - 检查慢日志里高频出现的SQL是否都满足:有确定的分片键条件(如
WHERE order_id = ?)、无跨分片JOIN、无全字段SELECT *
运维变更是否已实质影响线上稳定性?
这不是分库分表的触发条件,反而是劝退信号:
- 加索引、改字段等DDL操作必须选在凌晨低峰期,且每次耗时 >
30分钟,期间主库CPU/IO持续90%+,备库延迟飙升至小时级 - 你已经在用
gh-ost或pt-online-schema-change,但依然不敢在高峰期操作——说明当前架构已到维护极限 - 注意:如果只是“不敢动”,但没实际出过事,优先升级到MySQL 8.0(支持原子DDL、秒级加字段),或引入列存分析库(如ClickHouse)分流统计压力,比硬上分库分表成本低得多
真正要动手前,最容易被忽略的是分片键选择和后续的跨分片查询治理。一个错位的分片键(比如用时间做唯一分片键)会导致热点集中;而缺乏统一路由层或应用层兜底逻辑,会让分库分表变成“分布式单点故障放大器”。











