分库分表中,如何预估需要分多少个库?多少张表?

#中间件#面试八股

分库分表中,如何预估需要分多少个库?多少张表?

结论:分表数量由「数据量」决定,分库数量由「写入 QPS 与连接数」决定,两者不要混为一谈。算法是:用三年后的行数除以单表容量阈值得到表数,向上取到 2 的幂;再用单库可承载的写 QPS 与表数量上限得到库数。宁可多留一档,也不要一年后被迫二次拆分。

一、两个维度分别估算

维度输入阈值(经验值)输出
表数量三年后行数、单行大小单表 500 万到 1000 万行,或 2 GB表数 = ⌈行数 / 阈值⌉
库数量峰值写 QPS单库写 2000 到 5000 QPS库数 = ⌈写 QPS / 单库能力⌉
连接数应用实例数 × 池大小单库活跃连接不超过 800总连接 / 库数
每库表数运维与元数据开销每库 32 到 128 张较舒适校验 DDL 成本

二、算例

订单表当前 8000 万行,年增长 60%,单表目标 1000 万行:

时点预估行数需要表数向上取 2 的幂
当前0.80 亿88
第 1 年1.28 亿1316
第 2 年2.05 亿2132
第 3 年3.28 亿3364

若峰值写 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 的真实数据校准估算,别拍脑袋。
笔记加载中…