← 每日面试题 学习看板

什么是分库?分表?分库分表?

面试题/03数据库中间件/04分库分表/什么是分库?分表?分库分表?.md

面试记录 2026-09-23

题目:什么是分库?分表?分库分表?

难度:low

标签:db/sharding, general/knowledge, difficulty/low

评分:⭐⭐⭐⭐☆(4/5)

我的回答

分库分表,首先你要理解为什么要进行分库分表。核心原因是数据库的单表能力在数量级达到一定程度之后,它的搜索遍历一定会降低,搜索遍历的效率一定会降低。原因是它本身 B 加树的索引层数会一来一点点变高,在数量增长之后。当层高高过一定量级之后,会影响数据从磁盘中加载的速率,因为每高一层,它就要多进行一次磁盘遍历。啊,这是核心的要进行分库分表的原因。把数据分到不同的表上,是为了分到不同的数据文件。这是分表,然后分库的原因其实是,单库其实是单库在承载能力上,其实它是有上限的。它承担的并发量也好,它承担的网络 IO 也好,读取能力连接池,这些它单库都是有上限的。分库之后,由多个库提供,同时提供它的不同表的数据查询,这时候把数据库的压力释放出来。把单个库的压力释放到多个库中,这时候可以更好地提升服的承载能力,也提升服务的安全性和稳定性,因为哪怕单个库出现了问题,多个库也可以正常使用。另外常见的还有一个分区,表分区,分区表。单个表对外还是单个表,在同一个库上。但是这个表下属的数据按照一定的规则,比如时间或者是某个键的创建逻辑多少多少。然后把数据分到不同的分区表上,数据库的不同的数据文件上。这时候它也能提升数据库查询的并发能力,支撑的数据呀能力。它本身其实和分表是一个概念,但是它最外侧没有把表名分开,而是同一个表名,根据数据的不同特性分配到不同的数据文件上,也能提升能力。好处是原有的业务逻辑不用考虑改动,表还是原来那个表名。但是数据能力上会有一定提高,但它有自身的缺陷。分区表在承载力上还是会有一定的上限的。

点评

优点:

不足:

补充:

完整讲解

第一部分:知识重点剖析

核心考点定位:能否清楚区分分库、分表、分区三种方案各自的动机、边界和适用场景。

知识点拆解:

  1. 单库瓶颈来源(分库的动机):连接池上限(max_connections)、单实例 QPS/TPS、磁盘 IO、CPU、内存;一个主库宕机会影响全部业务,故障域无法隔离。
  2. 单表瓶颈来源(分表的动机):B+ 树层高随行数增长,索引扫描的磁盘 IO 次线性增加;二级索引与聚簇索引数据文件过大;DDL 变更阻塞时间线性增长;扫描型 SQL 无法用索引完全覆盖。
  3. 分库 vs 分表:分库=水平维度扩"实例"(解决并发/连接/故障域),分表=水平维度扩"文件"(解决单文件尺寸/索引深度)。两者可独立也可组合成"分库分表"。
  4. 表分区(Partition)对比:分区对业务透明(SQL 无感知)、由存储引擎层实现、只在同一实例内分散文件;优点是运维简单、迁移方便;缺点是仍受单实例瓶颈约束,无法跨机器扩容。
  5. 演进路径与取舍:单机 MySQL → 读写分离 → 垂直拆分(按业务拆库)→ 水平分表 → 水平分库分表 → 分片中间件(ShardingSphere / Vitess / TiDB)。每一步都是"更痛之前先试更便宜的方案"。
  6. 触发阈值(业界经验):单表 500w-2000w 行 / 单库连接池打满 / B+ 树高度到 4 层 / 单机 QPS 打满。触发到 2 项以上就该做方案评估。

第二部分:考察方向与延伸递进

考察方向:

延伸递进面试题:

  1. 单表多大行数、什么 QPS 下你决定开始分库分表?
  1. 分库分表之后,跨分片的 JOIN、聚合、分页怎么处理?
  1. 分区表和分表在存储引擎层实现差异是什么?什么场景优先选分区?

第三部分:面试者参考回答(300-600 字口语化)

面试官您好,分库分表是数据库水平扩展的手段,但要先讲清楚分库和分表分别解决什么问题。

分表主要是解决"单表数据量过大"的问题。MySQL 用 B+ 树做索引,行数据量翻倍,B+ 树层高就可能从 3 涨到 4,每次查询要走的磁盘 IO 就多一次;同时数据文件过大也会拖慢备份、DDL、扫描型 SQL 的性能。所以分表本质是把一份数据水平切片到多张表里,每张表单独是一个 InnoDB 文件,索引深度和数据文件都被压缩到可管理范围。

分库解决的是"单实例承载能力到顶"的问题。一个 MySQL 实例有连接池上限、QPS/TPS 上限、CPU 和内存上限;而且单点故障会波及所有业务,故障域完全重叠。分库之后,多个实例分摊连接和 IO,故障域也被切开,一个库出问题不会全站挂。

实际工程里,分表和分库经常一起做,因为既然都要改造 SQL 路由了,不如把数据同时切到不同库的不同表里,用分片键把数据均匀分布。这就是所谓的"分库分表"。

另外还有一个容易混淆的概念——表分区。分区对业务是透明的,SQL 层还是同一个表名,MySQL 引擎在存储层按 HASH/RANGE/LIST 把数据分散到多个文件里。优点是零改造成本,适合归档型、时序型数据;缺点是仍然跑在同一个实例上,无法跨机器扩容,只是把瓶颈稍微往后推。

什么时候开始做分库分表?我一般看三个阈值:单表超过 500w 行、B+ 树高度到 4 层、单库连接数或 QPS 打满。这三条里命中任意两条,再结合业务增速倒推 3-6 个月,就是启动改造的窗口。而在真正上分片之前,通常会先试更便宜的方案:读写分离、垂直拆库、加缓存、加异构索引,能撑一段是一段。

分库分表不是白来的:跨分片 JOIN 要变应用层聚合、事务要引入 TCC 或本地消息表、主键要改成全局 ID、扩容要考虑数据迁移。这些都是后面几轮面试的高频追问点。