什么是分库?分表?分库分表?
面试考察点
- 概念清晰度:面试官想知道你是不是真懂这三者的区别,而不是把它们当成同一个东西混着讲。很多人一张嘴就把 “分库分表” 说成一个动作,这就露馅了。
- 场景判断力:什么时候单库扛得住、什么时候要分表、什么时候必须分库,这种判断能力比会用中间件更值钱。
- 架构演进意识:分库分表从来不是上来就干的,而是单库优化、读写分离、缓存这些都做完之后,仍然扛不住才考虑的方案。能不能讲清楚这个演进过程,体现的是真实的架构经验。
核心答案
先把三个概念一刀切清楚:
| 概念 | 做的事情 | 解决的问题 | 物理层面 |
|---|---|---|---|
| 分表 | 把一张大表拆成多张表 | 单表数据量过大(查询慢、DDL 卡) | 同一个数据库实例内 |
| 分库 | 把一个库拆成多个库 | 单库连接数、QPS、磁盘 IO 扛不住 | 多个数据库实例 |
| 分库分表 | 既拆库又拆表 | 数据量大 + 并发高,单库单表双双见顶 | 多实例 + 多表 |
一句话总结:分表解决 “数据多”,分库解决 “压力大”,分库分表解决 “又多又压”。
深度解析
一、为什么会出现 “数据多” 和 “压力大”
先看一个典型的 MySQL 性能瓶颈演进过程,这块很多文章一笔带过,但实际踩过坑的人都知道:
- 单表数据量超过 500 万行 / 2GB:阿里《Java 开发手册》官方建议的 “推荐分库分表” 阈值,B+ 树层级开始增加,查询开始变慢
- 单表数据量超过 2000 万行:这是行业广泛流传的 “性能拐点”,再优化收益也有限
- 单库 TPS / QPS 上来:连接池打满、锁竞争加剧、磁盘 IO 饱和
- 单库数据文件过大:备份、恢复、DDL 都变得极慢
单库单表的性能瓶颈
上面这条演进路线是面试加分项,一定要记住:分库分表是 “前面招都用完了还扛不住” 才上的最后招。我面试时常反问一句 “为什么不用读写分离和索引优化解决?”,能答上来的人不多。
分库分表前的优化路径
二、分表的两种姿势:垂直 vs 水平
垂直分表:把一张表的列拆开,按 “热冷字段” 或 “长短字段” 拆分。
比如 user 表有 30 个字段,把常用的 id、name、avatar 放主表,把不常用的 bio、address、extend_json 拆到扩展表。好处是热数据行变小,单页能装下更多行,缓冲池命中率提升。
水平分表:把一张表按行拆开,按某个分片键(如 user_id)路由到多张子表。
比如 order_0、order_1、order_2...order_15,16 张表存同一个逻辑 order 的数据。这是日常说的 “分表” 主流形态。
垂直分表和水平分表
上面两组拆法的核心差异:垂直分表减少的是 “列宽”,水平分表减少的是 “行数”。垂直分表治 “字段太杂”,水平分表治 “数据太多”。
垂直分表与水平分表对比
三、分库的两种姿势:垂直 vs 水平
跟分表一样,分库也分垂直和水平:
- 垂直分库:按业务边界拆。比如电商系统把
user_db、order_db、product_db、payment_db各自独立。这是微服务化的前置条件。 - 水平分库:同一个业务的库,按某个分片键拆成多个结构相同的库。比如
user_db_0、user_db_1、user_db_2,根据user_id % 3路由。
垂直分库和水平分库
垂直分库是 “业务问题”,为了解耦和扩展性;水平分库是 “性能问题”,为了分摊单库压力。
垂直分库与水平分库对比
四、分库分表:终极形态
把水平分库和水平分表叠在一起就是 “分库分表”。比如拆 4 个库,每个库 16 张表,一共 64 张子表:
水平分库分表架构
这种方案能扛住海量数据 + 高并发,但代价也大:跨库 Join、分布式事务、全局唯一 ID、运维复杂度全来了。所以一句话:不到万不得已不要上分库分表,上了就回不去了。
分库分表的收益与代价
五、Java 生态里的落地工具
| 工具 | 类型 | 特点 |
|---|---|---|
| ShardingSphere-JDBC | Client 端 | 改造轻量,无中间件,性能好 |
| ShardingSphere-Proxy | Proxy 端 | 对应用透明,运维友好 |
| MyCat | Proxy 端 | 老牌方案,社区活跃度下降 |
| TiDB / OceanBase | 分布式数据库 | 业务无感知,但成本高 |
Java 项目里最常见的是 ShardingSphere-JDBC,引入一个 Maven 依赖 + 配置分片规则就能用,比迁移到 TiDB 改造成本低得多。
面试高频追问
-
追问一:分片键怎么选?
按高频查询条件选。订单系统按
user_id分,因为买家视角查询最多。千万不要选create_time、id这种容易产生数据倾斜的字段。 -
追问二:分库分表后,跨库 Join 怎么办?
三种思路:业务层多次查询组装、把需要 Join 的表做 “绑定表” 或 “广播表”、把数据同步到 ES 做宽表查询。生产中 ES + 分库分表 的组合特别常见。
-
追问三:分库分表后分页查询怎么办?
全局分页是分库分表的老大难。常见做法:禁止跨页跳转、用游标分页(
WHERE id > last_id)、二次查询合并法。这是个深坑,能聊一整面。 -
追问四:分布式 ID 用什么?
雪花算法(Snowflake)、Leaf、TinyID、数据库号段。Snowflake 最经典,但要注意时钟回拨问题。
常见面试变体
- “什么时候该分库分表?数据量到多少?”
- “分库分表后怎么做数据迁移?双写方案怎么落地?”
- “ShardingSphere 的分片策略有哪几种?”
- “为什么大厂都用 Snowflake,不用数据库自增 ID?”
记忆口诀
分表治 “行多”,分库治 “压大”,分库分表一起上,能扛海量又能扛并发。
垂直拆是按业务/字段切,水平拆是按数据行切。记住这条线,三个概念不会混。
总结
分库分表不是银弹,是单库优化、读写分离、缓存都做完后的 “最后一公里”。回答时先把三个概念一刀切清楚(分表解决数据量、分库解决并发压力、分库分表两者皆治),再聊垂直 vs 水平、分片键选择、跨库 Join 这些落地的坑,面试官就知道你是真做过,而不是背的八股。