分库分表是数据与并发压力下的必选项,而非选择题;它解决查询变慢、连接池打满、磁盘io过高、alter table阻塞等真实问题,单表超800万行即需评估分表,超1000万行索引退化明显。

分库分表不是“该不该做”的选择题,而是“数据和并发已经压不住了”时的必选项。它解决的不是理论问题,是 SELECT * FROM orders WHERE user_id = ? 查询从 20ms 慢到 2s、连接池频繁 Too many connections、磁盘 IO 持续 95% 这类真实卡点。
单表超 1000 万行就该警惕
这不是拍脑袋的数字。MySQL 的 B+ 树索引在单表数据量超过 1000 万后,层级明显变深,ref 类型的等值查询开始退化为 range 甚至 index;EXPLAIN 中 rows 字段常显示几十万——说明优化器已放弃精准估算。更实际的是:ALTER TABLE 加字段操作可能阻塞写入数小时,备份窗口拉长到无法接受。
- 业务表(如
user、order)达到 800 万行时,就要启动分表评估 - 日志类、流水类表(如
payment_log)按月分表,哪怕单月只有 200 万,也建议提前切,避免某个月突增导致单表爆掉 - 不要等
SHOW TABLE STATUS显示Data_length超过 10GB 再行动——此时磁盘碎片和锁竞争已不可逆
并发连接数打满是分库的明确信号
MySQL 默认 max_connections=151,但真实可用连接远少于此(后台线程、复制线程、慢查询占用都会挤占)。当应用层频繁抛出 Cannot create PoolableConnection 或数据库监控里 Threads_connected 长期 >140,说明单库已成瓶颈。
- 分库能直接翻倍/三倍提升连接上限,但要注意:不同分库间不能共享连接,应用必须支持多数据源路由
- 如果只是读多写少,优先考虑读写分离而非分库;只有读写都扛不住时,才用分库把流量物理隔离
- 别用“分库”掩盖连接泄漏——先确认应用层是否未关闭
ResultSet或Connection
垂直拆分比水平拆分更容易落地,但容易被忽略
水平分表(按 ID 取模、按时间分片)常被当作“标准答案”,但 70% 的性能问题其实来自垂直设计不合理。比如把用户头像(BLOB)、简介(TEXT)、登录态(TINYINT)全塞进一张 user 表,每次查列表都要拖着几 MB 大字段走。
- 把大字段(
avatar、profile)拆到独立表,主表只留高频访问字段(id、name、status) - 业务耦合强的表(如
order和order_item)可保留在同一库,但弱关联表(如user_address)应拆到独立库,减少锁冲突 - 垂直拆分后,
JOIN查询会变少——这是好事,别强行用中间件拼 SQL,让应用层分步查
真正难的不是拆,是拆完之后的全局 ID、跨库事务、数据一致性这些事。很多团队卡在“怎么保证分片键不重复”上,却忘了先确认:当前慢查询是不是根本没走索引?连接池配置是不是太小?——分库分表是止血绷带,不是万能解药。











