分库分表
用途:判断单表/单库是否已到极限,以及如何设计分片方案
什么时候真的需要
「什么时候真的需要」小节链接先排除更便宜的方案:索引与 SQL 优化、读写分离、缓存、冷热数据分层、归档、垂直拆分(按业务拆库)、单表分区。分片是最后手段,因为它把复杂度转移给应用与运维。
经验阈值(非硬规则,取决于行宽与访问模式):单表数千万行或单表数百 GB、且优化后仍无法满足延迟目标时考虑水平分片。
分片键选择
「分片键选择」小节链接| 判据 | 说明 |
|---|---|
| 高频查询条件 | 绝大多数查询能带分片键,避免全分片扫描 |
| 数据分布均匀 | 避免热点(如按租户分片时大客户即热点) |
| 不可变 | 分片键变更意味着数据迁移 |
| 业务无关优先 | 用自增/趋势 ID 派生,避免用会调整的编码 |
常见策略:哈希取模(均匀,扩容需迁移)、一致性哈希(扩容迁移量小)、范围分片(易热点但利于区间查询)、基因法(把主表分片位嵌入二级表 ID,使二级表可按同键路由)。
跨分片问题清单
「跨分片问题清单」小节链接- 查询无分片键:广播查询代价高。对策:建立异构索引表(如按手机号→用户 ID 映射)、或把检索需求同步到搜索引擎。
- 分页与排序:各分片取
offset+limit再归并,深分页代价指数上升。对策:游标分页、限制可翻页深度。 - 分布式 ID:号段模式(DB 批量发号)、雪花(时钟回拨需处理)、数据库自增多主(步长配置)。要求趋势递增以保护主键索引局部性。
- 跨分片事务:尽量避免同事务写多分片;无法避免时用最终一致(本地消息表 + 对账)。
- 聚合计算:
COUNT/SUM需下推 + 汇总;复杂分析交给数仓或 OLAP 引擎。 - 扩容与再平衡:按 2 的幂翻倍分片可让迁移成“对半拆”,或采用虚拟分片(slot)层解耦物理节点。
- 全局唯一约束:唯一索引只在分片内有效,全局唯一需独立约束表或异步校验。
中间件形态
「中间件形态」小节链接| 形态 | 代表 | 特点 |
|---|---|---|
| 客户端 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 章(分区)