🗄️ 数据库分区 vs 分库分表

一文看清两种"拆数据"策略的本质区别、架构形态与适用场景

① 核心概念
🔵 数据库分区 Partition

仍是同一台数据库服务器,同一张逻辑表, 由数据库内核把数据按某个规则切成若干"物理片段" (分区)存储在不同的文件或存储组里。

对应用层完全透明,SQL 照常写,数据库自己决定查哪个分区。

🟠 分库分表 Sharding

将数据分散到多台数据库实例(分库)或多张真实表(分表)中, 应用通过中间件(Sharding-JDBC / MyCat 等) 或自己计算路由,把请求打到正确的库和表。

彻底突破单机存储和计算瓶颈,是真正的"水平扩展"。

② 架构形态对比
🔵 分区(Partition)架构
应用层 → 单一数据库实例
📱 Application
↓ 普通 SQL
🖥️ 单台 MySQL Server
逻辑表:orders(仍是一张表)
P0
2020年
P1
2021年
P2
2022年
P3
2023年
P4
2024年
P5
2025年
↑ 分区是同一服务器内的文件分片
✅ 优化点:查询时只扫描相关分区(分区裁剪),减少 I/O
VS
🟠 分库分表(Sharding)架构
应用层 → 中间件 → 多个数据库实例
📱 Application
⚙️ Sharding 中间件
(Sharding-JDBC / MyCat / Vitess)
↓ 按 user_id % 4 路由
🖥️ DB-0
orders_0user_id % 4 = 0
🖥️ DB-1
orders_1user_id % 4 = 1
🖥️ DB-2
orders_2user_id % 4 = 2
🖥️ DB-3
orders_3user_id % 4 = 3
✅ 优化点:每台服务器只承担 1/N 的数据量和计算压力
③ 分区的常见类型(MySQL 为例)
分区类型 规则 典型场景 示例
RANGE 按值范围划分 时间序列数据(日志、订单) PARTITION BY RANGE(YEAR(create_time))
LIST 按枚举值列表划分 地区、状态枚举等 PARTITION BY LIST(region_id)
HASH 按哈希值均匀分布 无明显规律的大表均匀分布 PARTITION BY HASH(user_id) PARTITIONS 8
KEY MySQL 自定义哈希函数 主键哈希分区 PARTITION BY KEY(id) PARTITIONS 4
④ 核心维度对比
维度 🔵 数据库分区 🟠 分库分表
扩展方式 垂直(单机内部) 水平(多台机器)
服务器数量 单台实例 多台实例(可动态扩容)
逻辑表数量 1 张逻辑表 N 张真实物理表
路由方 数据库引擎自动 应用代码 / 中间件
应用改造成本 (几乎不用改) (需接入中间件或重构)
突破内存瓶颈 ✗ 不能 ✓ 可以
突破磁盘容量上限 △ 有限(受单机磁盘限制) ✓ 可以
突破单机并发上限 ✗ 不能 ✓ 可以
跨分区/分片查询 数据库内部合并,较简单 需跨库 JOIN,实现复杂
事务支持 完整本地事务 需分布式事务(2PC/Saga)
运维复杂度 (多实例、数据迁移等)
适用数据量级 千万 ~ 数亿级(单机能撑) 数亿 ~ 万亿级(单机撑不住)
⑤ 分区的核心收益:分区裁剪(Partition Pruning)
查询 WHERE create_time BETWEEN '2024-01-01' AND '2024-12-31'
✅ 有分区(Range by year)
SQL 请求
引擎裁剪:
只扫 P4(2024)
I/O 减少 83%(6 个分区只扫 1 个)
|
❌ 无分区(普通大表)
SQL 请求
全表扫描
3 亿行
扫描所有数据,慢且耗 I/O
💡 关键前提:查询条件必须包含分区键,否则无法裁剪,优化效果为零!
⑥ 分库分表的路由原理
写入一条订单 order_id=10007, user_id=12345
Application
INSERT INTO orders...
中间件
Sharding-JDBC
路由计算
12345 % 4 = 1
DB-1
orders_1 表
常见路由策略
取模:user_id % N(均匀,但扩容难)
范围:按 ID 区间分(冷热不均)
一致性哈希:扩容时迁移量最小
目录表:用元数据表查路由(最灵活)
⚠️ 分库分表的新挑战
• 跨库 JOIN 无法直接做
• 全局唯一 ID 需要专门生成(雪花算法等)
• 分布式事务一致性难保障
• 扩容/缩容时数据迁移复杂
⑦ 何时用哪个?
🔵 用「数据库分区」的场景
📦数据量在 千万到数亿级,单机内存 + 磁盘足够支撑
🕐数据有明显的时间序列特征(日志表、订单历史),按时间分区后可快速归档旧分区
🔍查询条件经常带分区键(如按月/年查),能充分利用分区裁剪
💰团队规模小,不想引入中间件复杂度,改造成本敏感
🗑️需要快速清理历史数据(DROP PARTITION 远比 DELETE 快)
🟠 用「分库分表」的场景
🚀数据量超过单机极限(数十亿行以上),单机撑不住
写并发极高,单台 MySQL 的写吞吐成为瓶颈(如电商大促)
📈业务仍在高速增长,需要按需横向扩容,加机器就能解决问题
🌏需要多地域部署,数据按地区分片到不同数据中心
🏢大型互联网公司,已有中间件团队或成熟的 Sharding 框架可用
⑧ 选型决策流程
遇到"数据量大"问题时,如何选方案?
数据量大,查询慢
先加索引?
优化 SQL?
↓ 索引无效 / 已优化但还慢
单机 I/O 成瓶颈?
数据量 < 5亿?
是 → 考虑分区
↓ 单机确实撑不住 / 写并发极高
有能力引入
中间件/多实例?
是 → 分库分表
↓ 无法改造 / 成本太高
考虑换 NewSQL
(TiDB / PolarDB 等)
NewSQL 天然水平扩展,不需手动 Sharding,但有学习和运维成本
⑨ 一句话总结

🎯 本质区别

数据库分区 是「单机内部的文件组织优化」——同一台机器、同一张逻辑表,数据库引擎帮你把数据按规则切成物理片段,优化 I/O 扫描范围,对应用透明,代价低,但无法突破单机天花板

分库分表 是「跨机器的横向水平扩展」——真正把数据和压力分散到多台机器,能突破单机存储/内存/并发的极限,但代价是引入了路由复杂性、分布式事务、跨库查询等一系列新问题。

💡 类比理解:分区像把一个大文件柜里的文件按年份分隔归档(还是同一个柜子);分库分表像把文件拆到不同城市的多个仓库(完全不同的物理位置)。

Made with ❤️ · 数据库分区 vs 分库分表 对比图