一、分区表基础:从一张大表说起

先问大家一个问题:你手头有一张 10TB 的订单表,每天要查最近 7 天的数据,还要按月做统计报表。这张表索引建了、SQL 也优化了,可查询还是慢得像蜗牛。怎么办?

我早年在一家电商公司就遇到过这事。当时 DBA 团队想了各种办法,最后靠分区表解决了问题。说白了,分区表就是把一张大表拆成多个小表,但对应用层透明——你查的还是那张表,数据库自动帮你定位到正确的分区。

1.1 什么是表分区

表分区是一种物理存储层面的拆分技术。它把一张表的数据,按照某个规则(比如时间、地区、ID 范围)分散到不同的物理段中。每个段叫一个分区,分区可以独立管理、独立备份、独立查询。

举个例子,一张订单表按月份分区:

CREATE TABLE orders (
    order_id    BIGINT,
    order_date  DATE,
    customer_id INT,
    amount      DECIMAL(10,2)
)
PARTITION BY RANGE (YEAR(order_date), MONTH(order_date)) (
    PARTITION p202401 VALUES LESS THAN (2024, 2),
    PARTITION p202402 VALUES LESS THAN (2024, 3),
    PARTITION p202403 VALUES LESS THAN (2024, 4),
    PARTITION p_future VALUES LESS THAN MAXVALUE
);

你看,数据按年月自动落入对应分区。查询时如果带上 order_date 条件,数据库直接跳过无关分区——这就是分区裁剪的核心。

核心概念:分区裁剪(Partition Pruning)是指查询优化器根据 WHERE 条件,只扫描匹配的分区,忽略不相关的分区。这是分区表性能提升的根本来源。

1.2 分区表的优势

我总结下来,分区表有四大好处:

优势 说明 我见过的场景
查询性能提升 只扫描相关分区,减少 I/O 某金融系统月报查询从 45 秒降到 3 秒
管理更灵活 可单独备份、重建、压缩某个分区 历史数据归档时只操作旧分区,不影响在线业务
数据清理高效 直接 TRUNCATE 分区,比 DELETE 快百倍 日志表保留 90 天,到期直接删分区
并行能力增强 多分区可并行扫描 大数据量聚合查询,分区并行后吞吐翻倍

嗯,这里要注意:分区表不是银弹。如果查询条件不带分区键,反而可能比普通表更慢——因为优化器要扫描所有分区的元数据。

1.3 适用场景

我个人习惯把适用场景分成三类:

  • 时间序列数据:日志、订单、交易流水。这类数据天然按时间增长,查询也常带时间范围。
  • 大表数据归档:比如保留最近 3 个月数据,历史数据移到冷分区。我曾经帮一个客户把 5TB 的审计表按月分区,清理效率提升了 20 倍。
  • 按地域或业务线拆分:比如按省份分区,查询时只扫本省数据。
我的建议:表数据量超过 500GB,或者单表行数超过 1 亿,就可以考虑分区。小于这个量级,分区带来的管理成本可能超过收益。

1.4 分区键的选择原则

分区键选错了,分区表就废了。我踩过这个坑——曾经按订单状态分区,结果 90% 的数据都在「已完成」分区,其他分区几乎空着。这叫分区倾斜,性能还不如不分区。

选分区键,记住三条原则:

  1. 高频查询条件:分区键必须是 WHERE 子句里最常用的字段。你想想看,如果查询很少带分区键,分区裁剪就失效了。
  2. 数据分布均匀:每个分区的数据量要差不多。避免某个分区特别大,其他分区特别小。
  3. 分区数量适中:分区太多(比如上千个)会导致元数据膨胀,DDL 操作变慢。我一般建议控制在 50~200 个分区。

举个例子,订单表按 order_date 分区就比按 order_status 好——时间天然均匀分布,而且查询常带时间范围。

避坑指南:我曾经见过有人用 UUID 做分区键,结果每个分区数据量完全随机,查询时几乎要扫描所有分区。分区键一定要有业务意义,且查询模式可预测。

1.5 分区表的知识体系

下面这张图帮你理清分区表的核心脉络:

分区表知识体系图 分区表知识体系 表分区 定义与原理 四大优势 适用场景 分区键原则 物理拆分 透明访问 查询加速 管理灵活 时间序列 数据归档 高频查询 均匀分布 数量适中 核心:分区裁剪是性能提升的根本 查询必须带分区键,否则分区表优势尽失

1.6 小结

分区表的核心就一句话:把大表拆小,让查询只扫该扫的数据。选对分区键,分区裁剪才能生效。我见过太多人分区键选错了,最后分区表反而成了性能瓶颈。