← 返回题目列表

MySQL 分区表和分库分表有什么区别?什么时候用?

高频 困难 第 18 / 28 题 更新于 2026/07/27
MySQL分区表分库分表数据库架构

简化版

分区表是在同一个 MySQL 实例内把一张表按规则拆成多个分区,对应用基本透明;分库分表是把数据拆到多个表甚至多个库,应用或中间件要参与路由。分区主要解决单表管理和部分查询裁剪问题,分库分表主要解决单机容量、写入和连接压力问题。

详细版

对比:

维度分区表分库分表
拆分位置同一实例内多表、多库、可跨实例
应用感知较低较高
主要目标分区裁剪、历史数据管理扩展容量和吞吐
查询路由MySQL 优化器处理应用或中间件处理
运维复杂度中等

分区适合按时间管理历史数据、按范围删除归档、查询条件常带分区键的场景。分库分表适合单机容量或写入压力扛不住、单表过大且业务可按 shard key 路由的场景。

完整版教学

一、分区表不是分布式

分区表仍在一个 MySQL 实例里。它把一张逻辑表拆成多个物理分区,优化器在查询时如果能根据分区键判断只访问部分分区,就可以做分区裁剪。

比如按月份分区的订单表,如果查询条件带 create_time,就可能只扫目标月份分区。如果查询不带分区键,仍可能扫多个分区,收益会下降。

假设订单表按月份分 24 个分区,查询 where create_time >= '2026-07-01' and create_time < '2026-08-01',优化器可以只访问 7 月分区;如果查询 where user_id=1001 且不带时间,可能需要检查多个分区。分区表的收益来自分区裁剪和管理便利,不是自动把单机能力变成 24 台机器。

一台 MySQL 实例:
orders 逻辑表
  |- p202601
  |- p202602
  |- p202603

CPU、内存、I/O 仍主要受这一台实例限制。

二、分区表适合什么问题

分区表常见价值:

  • 历史数据按时间分区,归档和删除更方便;
  • 查询经常带分区键,可以减少扫描范围;
  • 单表数据很大,但还没到必须跨实例扩展;
  • 运维上希望按分区管理数据。

它不适合解决所有性能问题。如果 SQL 不带分区键,或者瓶颈是单机 CPU、I/O、连接数,分区表作用有限。

分区表特别适合历史数据生命周期管理。比如日志表每天 500 万行,保留 180 天,如果按天或月分区,删除历史数据可以通过丢弃旧分区完成,比大范围 delete 更轻。查询近 7 天日志时,如果条件带时间,也能裁剪掉旧分区。它解决的是“单实例内更好管理和裁剪”,不是解决跨机器水平扩展。

需求分区表是否适合原因
按时间归档删除适合可按分区快速管理历史数据
查询总带时间范围较适合可做分区裁剪
单机写入打满不够仍在同一实例内
跨用户水平扩展不够需要分库分表或分布式方案

记忆钩子:分区表像把一个柜子分抽屉,分库分表像把柜子搬到多间房;前者方便管理,后者解决空间和吞吐扩展。

三、分库分表解决的是扩展性

分库分表把数据按 shard key 拆到多个库或表。比如按 user_id 取模,把用户订单分散到 16 张表或多个实例。

好处是容量和写入压力可以水平扩展;代价是应用复杂度上升:

  • 查询必须带 shard key 才好路由;
  • 跨分片 JOIN 很难;
  • 全局唯一 ID 要单独设计;
  • 跨分片事务复杂;
  • 扩容迁移成本高。

用数字看更直观:单库每秒稳定承载 5000 写入,如果业务增长到每秒 3 万写入,单靠分区表仍然压在同一实例上;分成 8 个库后,理想情况下写入可以分摊到多个实例。但代价是查询必须路由,跨分片聚合和排序会变复杂,事务一致性也更难。

四、什么时候不要急着分库分表

分库分表是架构手术,不是普通 SQL 优化。很多问题先用这些手段解决:

  • 补合适索引;
  • 冷热数据归档;
  • 读写分离;
  • 缓存热点数据;
  • 优化 SQL 和分页;
  • 使用汇总表或搜索系统。

只有单机容量、写入吞吐、表大小和业务增长趋势确实逼近瓶颈时,再考虑分库分表。

这个判断要基于指标,不要因为“单表 1000 万行”就立刻拆。1000 万行但查询都命中主键和高质量联合索引,可能很稳;500 万行但写入热点集中、无索引大扫描、高并发统计,也可能很糟。先证明瓶颈在哪里,再选择拆分手段。

五、分片键选择很关键

分库分表最怕 shard key 选错。好的分片键应该:

  • 高频查询能带上;
  • 数据分布均匀;
  • 写入不会集中到单个分片;
  • 业务边界清晰;
  • 后续扩容可迁移。

如果订单按 user_id 分片,查某个用户订单很方便;但按商家聚合、全局时间排序就会变复杂。

分片键一旦选定,后续所有查询都会被它影响。user_id % 16 能均匀分散用户订单,但如果大量查询是按 merchant_id 查订单,就会变成跨 16 个分片汇总。分片键不是单纯看分布均匀,还要看核心查询是否能带上它。

六、分区和分库分表的查询差异

分区表对应用基本透明,SQL 仍写同一张表,优化器负责判断访问哪些分区。分库分表通常需要应用或中间件根据 shard key 路由到具体库表;如果没有 shard key,可能要广播查询所有分片,再合并结果。

分区表查询:
select ... from orders where create_time between ...
MySQL 内部裁剪分区

分库分表查询:
应用/中间件根据 user_id -> 定位 order_03
没有 user_id -> 多分片查询并合并

七、常见误区与追问

  • 误区:分区表就是分库分表。 分区表仍在一个 MySQL 实例内,应用感知低;分库分表可跨库跨实例,需要路由和分片治理。
  • 误区:分区表能解决单机写入瓶颈。 分区表主要帮助裁剪和管理,CPU、内存、I/O 仍受单实例限制。
  • 误区:表大就必须分库分表。 是否拆分要看索引、查询模式、容量、写入吞吐和增长趋势,不能只看行数。
  • 误区:分片键只要分布均匀就好。 分片键还必须匹配高频查询,否则大量请求会变成跨分片广播。
  • 追问:分区表最适合什么场景? 按时间管理历史数据、查询常带分区键、需要快速归档或删除旧分区的场景。
  • 追问:分库分表会带来哪些代价? 跨分片 JOIN、全局排序、分布式事务、全局 ID、扩容迁移和运维复杂度都会上升。

八、加强记忆

分区表是在同一实例内把一张逻辑表拆成多个分区,主要价值是分区裁剪和历史数据管理;分库分表是把数据拆到多个表、多个库甚至多个实例,主要目标是扩展容量和吞吐。能通过索引、归档、缓存、读写分离和汇总表解决的,不要急着做分库分表;真要拆,先选对 shard key,并接受跨分片查询、事务、排序和扩容迁移的复杂度。