分库分表中,如何预估需要分多少个库?多少张表?
结论:分表数量由「数据量」决定,分库数量由「写入 QPS 与连接数」决定,两者不要混为一谈。算法是:用三年后的行数除以单表容量阈值得到表数,向上取到 2 的幂;再用单库可承载的写 QPS 与表数量上限得到库数。宁可多留一档,也不要一年后被迫二次拆分。
一、两个维度分别估算
| 维度 | 输入 | 阈值(经验值) | 输出 |
|---|---|---|---|
| 表数量 | 三年后行数、单行大小 | 单表 500 万到 1000 万行,或 2 GB | 表数 = ⌈行数 / 阈值⌉ |
| 库数量 | 峰值写 QPS | 单库写 2000 到 5000 QPS | 库数 = ⌈写 QPS / 单库能力⌉ |
| 连接数 | 应用实例数 × 池大小 | 单库活跃连接不超过 800 | 总连接 / 库数 |
| 每库表数 | 运维与元数据开销 | 每库 32 到 128 张较舒适 | 校验 DDL 成本 |
二、算例
订单表当前 8000 万行,年增长 60%,单表目标 1000 万行:
| 时点 | 预估行数 | 需要表数 | 向上取 2 的幂 |
|---|---|---|---|
| 当前 | 0.80 亿 | 8 | 8 |
| 第 1 年 | 1.28 亿 | 13 | 16 |
| 第 2 年 | 2.05 亿 | 21 | 32 |
| 第 3 年 | 3.28 亿 | 33 | 64 |
若峰值写 QPS 为 1.2 万、单库可承载 3000,则库数 = 4,最终形态是 4 库 × 16 表 = 64 张物理表。若写 QPS 只有 2000,2 库 × 32 表也够——分表数量不必等于分库数量。
表数 = 64(数据量决定,取 2 的幂)
│
├── 库数 = 4(写入能力决定),每库 16 张表
├── 连接校验:8 实例 × 20 连接 × 4 库 = 640 < 800 ✅
└── 单表校验:3.28 亿 / 64 ≈ 512 万行 < 1000 万 ✅
三、采集真实数据
-- 当前数据量与增长趋势
SELECT table_name,
table_rows,
ROUND(data_length / 1024 / 1024) AS data_mb,
ROUND(index_length / 1024 / 1024) AS index_mb,
ROUND((data_length + index_length) / 1024 / 1024) AS total_mb
FROM information_schema.tables
WHERE table_schema = 'order_db'
AND table_name LIKE 't_order%';
-- 单行平均长度,用于从行数推算容量
SELECT AVG_ROW_LENGTH,
(data_length + index_length) / table_rows AS bytes_per_row
FROM information_schema.tables
WHERE table_schema = 'order_db'
AND table_name = 't_order';
table_rows 是采样估算值;需要精确值就在从库低峰执行一次 SELECT COUNT(*),别在主库高峰做。
四、常见追问
Q1:分多了有什么坏处? 连接池、备份任务、DDL 与监控对象成倍增加;跨分片查询的扇出更严重;单表数据太少会让索引选择性变差、缓存命中率下降。
Q2:分少了怎么办? 只能二次拆分,代价接近重建。所以业界偏爱「逻辑分片一次定够(如 1024),物理表按需展开」,用路由层吸收扩容。
Q3:按三年还是五年规划? 按三年。硬件成本逐年下降,业务形态变化快,五年预测的误差通常大于省下的扩容成本。
Q4:写入 QPS 怎么估? 峰值 QPS ≈ 日订单量 × 峰值系数 / 86400。电商大促的峰值系数常取 5 到 10,再留 30% 余量。
Q5:分片数估错了能补救吗? 能,但代价不同:逻辑分片预留够(例如 1024 个槽)时,扩容只是搬表;物理表数量写死时,只能新建集群双写迁移,工期以月计。
这也是「宁可多留一档」的原因——多分一倍的成本,远低于二次拆分。
小结
- 表数看容量,库数看写入与连接数,二者独立计算。
- 结果向上取到 2 的幂,并预留一档扩容空间。
- 用
information_schema的真实数据校准估算,别拍脑袋。