问题
什么时候需要分库分表?
答案
1. 核心判断标准
分库分表是一项复杂的架构决策,需要在收益与成本之间权衡。以下是常见的判断指标:
| 维度 | 临界值参考 | 说明 |
|---|---|---|
| 单表数据量 | 500万 - 1000万行 | 超过后查询性能明显下降,索引效率降低 |
| 数据库连接数 | 接近最大连接数的80% | MySQL默认151,达到瓶颈需要分库 |
| 单库QPS | 3000 - 5000 | 单库并发压力过大,响应时间变长 |
| 磁盘容量 | 达到单机容量的70% | 存储空间不足,需要横向扩展 |
| 单表文件大小 | 10GB以上 | 影响备份恢复、DDL操作的执行时间 |
2. 需要分库分表的典型场景
场景1:单表数据量过大
// 典型案例:订单表
// 日订单量:100万
// 保留时长:3年
// 预估数据量:100万 × 365 × 3 ≈ 10亿条
// 问题表现:
// 1. 分页查询耗时:SELECT * FROM order LIMIT 10000000, 20; // 耗时>5秒
// 2. 索引失效:B+树层级过深,索引查询效率降低
// 3. 统计查询慢:COUNT(*)、聚合查询全表扫描
解决方案:水平分表,按时间或ID范围拆分
场景2:并发写入压力大
// 典型案例:秒杀系统
// 峰值QPS:10000
// 单库最大QPS:3000
// 问题表现:
// 1. 数据库连接池耗尽
// 2. CPU使用率持续100%
// 3. 慢查询日志大量堆积
// 4. 锁等待时间增加
解决方案:水平分库,将并发压力分散到多个数据库实例
场景3:业务复杂度高,耦合严重
// 典型案例:电商系统
// 单库包含:用户、订单、商品、库存、支付、物流等30+张表
// 问题表现:
// 1. 不同业务团队开发冲突
// 2. 某个模块故障影响整个系统
// 3. 数据库备份时间过长
// 4. 无法针对不同业务做精细化优化
解决方案:垂直分库,按业务领域拆分
场景4:读写分离后仍然性能不足
// 已实施读写分离,但:
// 1. 从库数量已达5个,同步延迟仍然明显
// 2. 主库写入压力仍然过高
// 3. 单表数据量过大,读从库也很慢
解决方案:在读写分离基础上,进一步实施分库分表
3. 何时不需要分库分表
| 情况 | 建议 |
|---|---|
| 数据量小于500万 | 优先优化索引、SQL、缓存 |
| 并发不高 | 通过垂直扩展(升级硬件)解决 |
| 业务简单 | 保持单库单表,降低维护成本 |
| 团队技术储备不足 | 先通过读写分离、缓存等简单方案过渡 |
4. 分库分表的时机选择
// 推荐的演进路线:
// 阶段1:单库单表 → 优化索引、SQL
// 阶段2:读写分离 → 解决读压力
// 阶段3:引入缓存 → 降低数据库压力
// 阶段4:垂直分库 → 按业务拆分
// 阶段5:水平分表 → 解决单表数据量问题
// 阶段6:水平分库 → 解决并发和存储问题
// 实际决策示例
public class ShardingDecision {
public boolean needSharding(TableMetrics metrics) {
// 满足任一条件即考虑分库分表
return metrics.getRowCount() > 10_000_000 // 数据量超1000万
|| metrics.getTableSizeGB() > 10 // 表文件超10GB
|| metrics.getQps() > 5000 // QPS超5000
|| metrics.getConnectionUsageRate() > 0.8 // 连接使用率超80%
|| metrics.getSlowQueryRate() > 0.1; // 慢查询率超10%
}
}
5. 决策前的准备工作
在决定分库分表前,务必做好以下评估:
- 容量规划
// 预估未来1-3年的数据增长量 long dailyGrowth = 1_000_000; // 日增长100万 int retentionDays = 365 * 3; // 保留3年 long totalRows = dailyGrowth * retentionDays; // 约10亿 // 计算需要的分片数 long maxRowsPerShard = 10_000_000; // 单表最大1000万 int shardCount = (int) Math.ceil(totalRows / (double) maxRowsPerShard); // 结果:需要100个分片 - 成本评估
- 开发成本:改造应用代码、中间件集成
- 运维成本:监控、备份、扩容的复杂度增加
- 测试成本:需要更全面的测试覆盖
- 风险评估
- 数据迁移风险:历史数据如何平滑迁移
- 兼容性风险:现有业务逻辑是否需要大幅改造
- 回滚方案:分库分表后如何回退
6. 核心要点总结
- 分库分表不是银弹,应该是在其他优化手段(索引优化、读写分离、缓存)无法解决问题时的选择
- 单表数据量超过1000万或单库QPS超过5000时,应认真考虑分库分表
- 提前规划比临时抱佛脚更重要,在业务初期就应考虑扩展性
- 先垂直后水平:优先按业务垂直拆分,再根据数据量水平拆分
- 评估成本:分库分表会带来复杂度上升,需要团队有相应的技术储备和运维能力