题目:什么是分库?分表?分库分表?
难度:low
标签:db/sharding, general/knowledge, difficulty/low
评分:⭐⭐⭐⭐☆(4/5)
分库分表,首先你要理解为什么要进行分库分表。核心原因是数据库的单表能力在数量级达到一定程度之后,它的搜索遍历一定会降低,搜索遍历的效率一定会降低。原因是它本身 B 加树的索引层数会一来一点点变高,在数量增长之后。当层高高过一定量级之后,会影响数据从磁盘中加载的速率,因为每高一层,它就要多进行一次磁盘遍历。啊,这是核心的要进行分库分表的原因。把数据分到不同的表上,是为了分到不同的数据文件。这是分表,然后分库的原因其实是,单库其实是单库在承载能力上,其实它是有上限的。它承担的并发量也好,它承担的网络 IO 也好,读取能力连接池,这些它单库都是有上限的。分库之后,由多个库提供,同时提供它的不同表的数据查询,这时候把数据库的压力释放出来。把单个库的压力释放到多个库中,这时候可以更好地提升服的承载能力,也提升服务的安全性和稳定性,因为哪怕单个库出现了问题,多个库也可以正常使用。另外常见的还有一个分区,表分区,分区表。单个表对外还是单个表,在同一个库上。但是这个表下属的数据按照一定的规则,比如时间或者是某个键的创建逻辑多少多少。然后把数据分到不同的分区表上,数据库的不同的数据文件上。这时候它也能提升数据库查询的并发能力,支撑的数据呀能力。它本身其实和分表是一个概念,但是它最外侧没有把表名分开,而是同一个表名,根据数据的不同特性分配到不同的数据文件上,也能提升能力。好处是原有的业务逻辑不用考虑改动,表还是原来那个表名。但是数据能力上会有一定提高,但它有自身的缺陷。分区表在承载力上还是会有一定的上限的。
优点:
不足:
补充:
核心考点定位:能否清楚区分分库、分表、分区三种方案各自的动机、边界和适用场景。
知识点拆解:
考察方向:
延伸递进面试题:
面试官您好,分库分表是数据库水平扩展的手段,但要先讲清楚分库和分表分别解决什么问题。
分表主要是解决"单表数据量过大"的问题。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、扩容要考虑数据迁移。这些都是后面几轮面试的高频追问点。