跳转至

分库分表能否无限扩容?

结论

不能无限扩容。分库分表在数据量初期解决了单表性能问题,但随着节点增加,会引入分布式事务、跨库 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 BYORDER BYCOUNT(*) 要聚合所有分片,性能差。

四、实际建议

  1. 能不分就不分:先靠索引、缓存、读写分离解决。
  2. 必须分,选对分片键:按访问频率最高的字段分片,避免跨分片查询。
  3. 预估 3~5 年数据量,一次规划好分片数,避免频繁扩容。
  4. 用成熟中间件:ShardingSphere、Vitess。
  5. 冷热分离:老数据归档到历史库 / 对象存储。

五、什么时候到头了

  • 分片数到几十上百,运维成本超过收益。
  • 上分布式数据库(TiDB、OceanBase),用户透明分片。

面试加分

  • 分库分表是用复杂度换性能,不是银弹。
  • 答出"分片键选择"和"扩容 rehash 问题"是重点。