一、垂直分库
定义
垂直分库是指按照业务模块 将数据库拆分成多个独立的库。例如,将原本在一个库中的用户表、订单表、商品表分别拆分到 user_db、order_db、product_db 中,每个库只负责自己业务域的数据。
解决的问题
- 单库连接数瓶颈:单个数据库实例的连接数是有限的,当所有业务表集中在一个库中时,连接数会被所有业务抢占。拆分后,每个业务模块独享数据库连接资源。
- 单库I/O与CPU瓶颈:高频的读写操作集中在同一个数据库上,磁盘I/O和CPU负载容易达到上限。不同业务模块的负载可以分散到不同的数据库实例上。
- 表之间的锁竞争:不同业务表之间的行锁、表锁在同一个库中会相互影响(例如,对订单表的频繁写入可能会影响用户表的查询)。拆分后锁范围被隔离在各个业务库内。
- 数据库维护与部署耦合:单个大库的备份、扩容、迁移都需要整体操作,影响所有业务。垂直拆分后,每个库可以独立部署、独立扩缩容、独立备份。
优点
- 业务解耦清晰:每个库对应一个业务域,团队可以各自维护自己的数据库,职责边界明确。
- 资源隔离:不同业务模块的数据库负载不会互相干扰,例如订单高峰不会拖慢用户登录。
- 扩展灵活:可以针对高负载的业务库单独升级硬件或增加只读副本,成本可控。
- 安全性提升:可以按业务域设置不同的数据库访问权限,敏感数据更容易管控。
缺点
- 跨库查询困难:原本在同一个库中可以轻松 JOIN 的表,拆分后无法直接跨库 JOIN,需要业务层做聚合查询或引入中间件。
- 分布式事务问题:涉及多个业务库的数据修改(如用户下单需要同时扣库存和创建订单),无法使用单库本地事务,需要引入分布式事务方案(如 TCC、Saga、Seata),复杂度显著增加。
- 拆分粒度难以把握:拆得太细会导致大量跨库调用,拆得太粗又达不到解耦效果。合理的拆分粒度依赖对业务边界的深入理解。
- 无法解决单表数据量过大的问题:如果某个业务表本身数据量巨大(如订单表达到数亿行),垂直分库并不能解决单表查询性能下降的问题。
二、水平分库
定义
水平分库是指将同一个表的数据 按照某种拆分规则(如取模、哈希、范围)分散到多个数据库实例中,每个库存储表的一部分数据行,但所有库的表结构完全相同。例如,将用户表按 user_id % 4 分到 4 个库中,每个库各存 1/4 的用户数据。
解决的问题
- 单表数据量过大:当一张表的数据量达到千万甚至亿级别时,即使有索引,B+树深度增加,查询性能也会显著下降。水平分库将数据分散到多个库,每个库的数据量缩小到原来的 1/N。
- 单库写入瓶颈:高并发写入场景下,单个数据库的写入吞吐量有上限。水平分库可以将写入压力分散到多个数据库实例,总吞吐量线性扩展。
- 单库磁盘容量限制:单台服务器的磁盘容量有限,水平分库可以利用多台服务器的存储资源,突破单机容量上限。
- 单库查询性能瓶颈:大表的全表扫描、范围查询、排序等操作在单库中会消耗大量 CPU 和内存。拆分后,相同的查询操作落在更小的数据集上,响应速度更快。
优点
- 突破单库容量上限:理论上可以无限扩展,通过增加数据库实例来承载不断增长的数据量。
- 写入吞吐量线性提升:N 个数据库实例的写入能力大致是单库的 N 倍,非常适合高并发写入场景。
- 大数据量下查询性能稳定:每个库的数据量可控,查询性能不会因总数据量增长而持续下降。
- 故障隔离:单个分片库宕机只影响该分片对应的那部分用户或数据,不会导致整个系统不可用。
缺点
- 跨分片查询复杂度高:分页、排序、聚合(COUNT、SUM、AVG)等操作需要从所有分片获取数据后在应用层合并,实现复杂且性能损耗大。
- 数据分布不均(热点问题):如果拆分键选择不当,某些分片的数据量或访问量远高于其他分片,导致"数据倾斜"------部分节点过载,部分节点空闲。
- 扩缩容代价巨大:当需要增加或减少分片数量时,一般需要重新计算数据分布并进行数据迁移,涉及大量数据的重新路由,停机时间较长。虽然可以通过一致性哈希等技术缓解,但仍是一个复杂运维问题。
- 分布式事务与全局一致性:跨分片的事务操作需要分布式事务方案来保证一致性,复杂度高且性能开销大。
- 跨分片联合查询支持有限:不同分片之间的 JOIN 查询无法直接执行,通常需要在应用层多次查询后合并,或者依赖数据库中间件(如 ShardingSphere、Vitess)。
- 拆分键选择至关重要 :拆分键决定了数据路由方式,一旦选定后期很难修改。如果业务查询模式发生变化,按原拆分键的查询效率会大幅下降。如果出现要以++多维度查询一张表++的情况,将难以确定拆分键。
三、两者对比总结
| 维度 | 垂直分库 | 水平分库 |
|---|---|---|
| 拆分方式 | 按业务模块拆分,不同表放到不同库 | 按数据行拆分,同一张表的数据分散到多个库 |
| 解决的核心问题 | 解决单库资源竞争、业务耦合、锁竞争 | 解决单表数据量过大、单库写入和存储瓶颈 |
| 数据量扩展能力 | 有限(每个业务库的单表数据量仍可能膨胀) | 强(通过增加分片可线性扩展) |
| 跨库查询 | 业务层聚合或引入中间件 | 复杂,分页/排序/聚合需在应用层合并 |
| 分布式事务 | 跨业务库时需处理 | 跨分片时需处理 |
| 扩缩容成本 | 较低(新增独立库即可) | 较高(需要重新分片和数据迁移) |
| 适用场景 | 业务复杂、模块间耦合高、需要资源隔离 | 单表数据量巨大、高并发写入、需要水平扩展 |
在实际架构中,垂直分库和水平分库通常不是互斥的,而是组合使用。先按业务模块做垂直分库,再对数据量大的业务表(如订单表、用户表)做水平分库,形成"先垂直后水平"的分层拆分策略,这也是大型互联网系统常见的数据库拆分方案。