分库分表能否无限扩容?¶
结论¶
不能无限扩容。分库分表在数据量初期解决了单表性能问题,但随着节点增加,会引入分布式事务、跨库 Join、扩容迁移、运维复杂度等一系列问题,最终会遇到瓶颈。
一、什么时候需要分库分表¶
- 单表数据量超过 1000 万行,或单表大小超过 10~20GB。
- 单库 QPS 达到瓶颈(通常几千~几万)。
- 单表 DDL 变更时间过长。
二、分片方式¶
1. 垂直拆分¶
- 垂直分库:按业务拆库(用户库、订单库、商品库)。
- 垂直分表:把大字段、不常用字段拆到扩展表。
2. 水平拆分¶
同一张表按某个字段(分片键)拆到多个库/表:
- 范围分片:按时间、ID 范围。优点:扩容简单;缺点:热点。
- Hash 分片:
userId % N。优点:分布均匀;缺点:扩容要 rehash。 - 一致性 Hash:扩容只迁移部分数据。
三、为什么不能无限扩容¶
1. 分布式事务成本¶
跨库操作(如下单要同时写订单库、库存库)需要分布式事务(Seata、TCC、本地消息表),性能下降、复杂度上升。
2. 跨库 Join 几乎不可用¶
原本一条 SQL 搞定的关联查询,要: - 业务层组装。 - 冗余字段。 - 用宽表 / ES。
3. 全局唯一 ID¶
自增主键在分库后失效,需要雪花算法、号段模式。
4. 扩容迁移成本¶
Hash 分片从 4 库扩到 8 库,几乎所有数据都要迁移。一致性 Hash 好一些,但仍要停机或双写。
5. 运维复杂度¶
- 多个实例监控、备份、主从。
- 数据倾斜要处理。
- 路由中间件本身成为瓶颈。
6. 聚合 / 排序 / 分页¶
GROUP BY、ORDER BY、COUNT(*) 要聚合所有分片,性能差。
四、实际建议¶
- 能不分就不分:先靠索引、缓存、读写分离解决。
- 必须分,选对分片键:按访问频率最高的字段分片,避免跨分片查询。
- 预估 3~5 年数据量,一次规划好分片数,避免频繁扩容。
- 用成熟中间件:ShardingSphere、Vitess。
- 冷热分离:老数据归档到历史库 / 对象存储。
五、什么时候到头了¶
- 分片数到几十上百,运维成本超过收益。
- 上分布式数据库(TiDB、OceanBase),用户透明分片。
面试加分
- 分库分表是用复杂度换性能,不是银弹。
- 答出"分片键选择"和"扩容 rehash 问题"是重点。