跳转到内容

分库分表

用途:判断单表/单库是否已到极限,以及如何设计分片方案

先排除更便宜的方案:索引与 SQL 优化、读写分离、缓存、冷热数据分层、归档、垂直拆分(按业务拆库)、单表分区。分片是最后手段,因为它把复杂度转移给应用与运维。

经验阈值(非硬规则,取决于行宽与访问模式):单表数千万行或单表数百 GB、且优化后仍无法满足延迟目标时考虑水平分片。

判据 说明
高频查询条件 绝大多数查询能带分片键,避免全分片扫描
数据分布均匀 避免热点(如按租户分片时大客户即热点)
不可变 分片键变更意味着数据迁移
业务无关优先 用自增/趋势 ID 派生,避免用会调整的编码

常见策略:哈希取模(均匀,扩容需迁移)、一致性哈希(扩容迁移量小)、范围分片(易热点但利于区间查询)、基因法(把主表分片位嵌入二级表 ID,使二级表可按同键路由)。

  1. 查询无分片键:广播查询代价高。对策:建立异构索引表(如按手机号→用户 ID 映射)、或把检索需求同步到搜索引擎。
  2. 分页与排序:各分片取 offset+limit 再归并,深分页代价指数上升。对策:游标分页、限制可翻页深度。
  3. 分布式 ID:号段模式(DB 批量发号)、雪花(时钟回拨需处理)、数据库自增多主(步长配置)。要求趋势递增以保护主键索引局部性。
  4. 跨分片事务:尽量避免同事务写多分片;无法避免时用最终一致(本地消息表 + 对账)。
  5. 聚合计算:COUNT/SUM 需下推 + 汇总;复杂分析交给数仓或 OLAP 引擎。
  6. 扩容与再平衡:按 2 的幂翻倍分片可让迁移成“对半拆”,或采用虚拟分片(slot)层解耦物理节点。
  7. 全局唯一约束:唯一索引只在分片内有效,全局唯一需独立约束表或异步校验。
形态 代表 特点
客户端 SDK ShardingSphere-JDBC 无额外网络跳,语言绑定
独立代理 ShardingSphere-Proxy、MyCat、Vitess 多语言接入、集中治理,多一跳与运维对象
云原生分布式数据库 TiDB、OceanBase、CockroachDB、PolarDB-X 对应用近似单库,代价是新的运维与成本模型

选型要点:是否接受额外组件故障域、扩容是否需要在线再平衡、SQL 兼容度、分布式事务与全局索引能力、可观测性。

双写(新旧同时写)→ 历史回填 → 双向校验(对账)→ 灰度切读 → 停旧写。每一步都要有回滚开关,且校验必须覆盖行数与关键字段。

误区 修正
一开始就分 1024 片 过度分片增加元数据与管理成本;按 2-3 年增长估算
分片键选错后靠广播查询兜底 性能不可控,等于没分片
忽视连接数放大 N 分片 × M 实例的连接总量会压垮数据库
用分片解决“业务查询模式问题” 检索类需求应交给搜索引擎/数仓
不做对账就切读 数据不一致无法发现
  • Apache ShardingSphere、Vitess、TiDB 官方文档
  • Martin Kleppmann《数据密集型应用系统设计》第 6 章(分区)