分库分表

分库分表是解决单机数据库性能瓶颈、支撑海量数据和高并发访问的核心架构手段。下面从「为什么做」「是什么」「怎么做」「常见问题」四个层面系统说明。


一、为什么要分库分表?

当业务发展到一定阶段,单机 MySQL / PostgreSQL 等关系型数据库往往会遇到以下问题:

问题 表现
数据量过大 单表几千万~上亿行,B+树层级变深,查询变慢
写入瓶颈 单点写入 TPS 上限明显,主库 CPU / IO 打满
连接数不足 应用扩容后,数据库连接池耗尽
锁竞争严重 大表 DML 导致行锁 / 表锁冲突
可用性风险 所有数据集中在一套库,故障影响面大

👉 目标:把数据拆到多个库、多个表中,降低单点压力,提高性能和扩展性。


二、什么是分库分表?

1️⃣ 分库(Sharding / Database Split)

把一个逻辑数据库拆成多个物理数据库实例:

  • 不同库部署在不同机器上
  • 每个库只存一部分数据
  • 库之间通常不做 JOIN

常见方式:

  • 垂直分库
  • 水平分库

2️⃣ 分表(Table Sharding)

把一个大表拆成多个结构相同的子表:

  • 每张表字段一致
  • 数据按规则分散到不同表
  • 查询时需要路由到正确的表

常见方式:

  • 垂直分表
  • 水平分表

三、四种常见拆分方式

1️⃣ 垂直分库(按业务拆分)

按业务模块拆分数据库

order_db
user_db
product_db
payment_db

✅ 优点:

  • 业务解耦
  • 降低单库复杂度
  • 便于独立扩容和维护

❌ 缺点:

  • 跨库 JOIN 困难
  • 分布式事务问题

📌 典型场景:微服务架构


2️⃣ 垂直分表(按字段冷热拆分)

将一张表的字段拆分到多张表

user_base(id, username, password)
user_profile(user_id, nickname, avatar)
user_ext(user_id, bio, settings)

✅ 优点:

  • 减少单行大小
  • 热点字段访问更快
  • 提升缓冲命中率

📌 典型场景:

  • 用户表、商品表
  • TEXT / JSON / BLOB 字段单独拆

3️⃣ 水平分表(单库内拆分)

表结构不变,数据行拆分

order_00
order_01
order_02
...
order_31

✅ 优点:

  • 降低单表数据量
  • 查询性能提升

❌ 缺点:

  • 需要路由逻辑
  • 跨表查询复杂

📌 常用于:单库还能撑住,但表太大


4️⃣ 水平分库分表(最彻底)

既分库又分表(真正的 Sharding)

db_0.order_00 ~ order_31
db_1.order_00 ~ order_31
db_2.order_00 ~ order_31

✅ 优点:

  • 突破单机容量和性能上限
  • 支持超大规模数据

❌ 缺点:

  • 架构复杂
  • 运维成本高
  • 分布式一致性挑战

📌 典型场景:

  • 电商订单
  • 支付流水
  • 日志 / 轨迹数据

四、分片键(Shard Key)怎么选?

这是分库分表成败的关键

✅ 好的分片键特征

  • 高频查询条件
  • 数据分布均匀
  • 不可变(尽量)
  • 基数大

❌ 不好的分片键

  • 状态字段(status)
  • 性别、类型等低基数字段
  • 随机 UUID(无业务意义)

常见示例

业务 分片键
订单 order_id / user_id
用户 user_id
交易流水 trans_id
日志 timestamp + hash

⚠️ 如果按 user_id 分片,但经常按 order_id 查,就需要映射表基因法


五、分片算法

算法 说明
取模分片 shard = id % N(简单但不利于扩容)
哈希分片 hash(id) % N(分布更均匀)
范围分片 按时间 / ID 区间(易产生热点)
一致性哈希 扩容迁移数据少(中间件常用)
基因法 分片键中嵌入分片信息

六、典型实现方案

1️⃣ 客户端分片(应用层)

  • 应用自己算路由
  • 直连多个数据源

✅ 性能好
❌ 代码侵入强


2️⃣ 中间件分片(主流)

中间件 特点
ShardingSphere Apache 顶级项目,功能完善
MyCat 老牌,偏 proxy
Vitess YouTube 开源,K8s 友好
TiDB NewSQL,自动分片

✅ 对业务透明
✅ 维护成本低
❌ 有一定性能损耗


3️⃣ 云厂商托管

  • 阿里云 DRDS / PolarDB-X
  • AWS Aurora + Sharding
  • 腾讯云 TDSQL

七、分库分表带来的挑战

问题 说明
分布式事务 XA / TCC / SAGA
全局唯一 ID Snowflake / Leaf / UUID
跨分片查询 聚合、排序、分页困难
扩容 数据迁移成本高
运维复杂度 监控、备份、DDL

📌 一句话:能不分就不分,分了就要接受复杂度


八、什么时候该分库分表?

✅ 建议考虑的信号

  • 单表 > 1000 万行(MySQL)
  • QPS > 5000~10000
  • 单机磁盘 > 1TB
  • 主库写入成为瓶颈
  • 业务持续增长预期明确

❌ 不建议过早分库分表

  • 数据量小
  • 访问模式不稳定
  • 团队缺乏分布式经验

九、一句话总结

分库分表本质是用复杂度换扩展性

  • 垂直拆分解决“耦合与臃肿”
  • 水平拆分解决“容量与性能”
  • 真正落地时,分片键设计和中间件选型比拆本身更重要
上一篇
下一篇