一、分区表基础:什么是分区表、优势与适用场景、分区键选择原则
1.1 分区表到底是什么?
先说说我对分区表的理解。说白了,分区表就是把一张大表,按某种规则拆成多个物理小表。但对外,它还是一张表。你查询的时候,SQL 还是写 SELECT * FROM orders,数据库自动帮你决定去哪个分区拿数据。
我记得刚入行时,有个同事把一张 5TB 的日志表扔在单个表空间里,查询慢得离谱。后来改成按月分区,同样的查询,速度提升了 20 倍。嗯,这就是分区表的魅力。
分区表的底层实现,其实就是一个「逻辑表 + 多个物理分区」的组合。每个分区有自己的数据文件、索引文件,甚至可以放在不同的磁盘上。
核心概念:分区表 = 逻辑上的单表 + 物理上的多段存储。对应用层透明,对 DBA 可控。
1.2 分区表的优势
我总结了四个核心优势,都是我在项目中实打实验证过的:
- 查询性能提升——分区裁剪(Partition Pruning)机制。你查 1 月份的数据,数据库只扫 1 月那个分区,其他分区碰都不碰。我见过一个案例,全表扫描要 40 秒,分区裁剪后降到 0.8 秒。
- 管理更灵活——你可以单独备份、恢复、重建某个分区,不用动整张表。我曾经在凌晨 2 点只重建了一个损坏的分区,业务完全无感知。
- 数据生命周期管理——旧数据直接 DROP 分区,比 DELETE 快几个数量级。DELETE 1 亿行可能要跑几小时,DROP 分区只要几秒。
- 并行处理能力——数据库可以同时扫描多个分区,充分利用多核 CPU。
| 对比维度 | 普通表 | 分区表 |
|---|---|---|
| 查询大范围数据 | 全表扫描,慢 | 分区裁剪,快 |
| 删除旧数据 | DELETE 慢,产生大量日志 | DROP 分区,秒级完成 |
| 备份恢复 | 只能整表操作 | 可分区级操作 |
| 索引维护 | 全局索引,重建成本高 | 局部索引,重建快 |
1.3 适用场景
不是所有表都适合分区。我见过有人把只有几千行的配置表也分了区,纯粹是给自己找麻烦。分区表最适合以下场景:
- 大表——单表数据量超过 100GB 或行数过亿,查询和维护开始吃力时。
- 有明显的时间维度——比如订单表、日志表、交易流水表。按月或按天分区,天然合适。
- 有明确的数据生命周期——比如只保留最近 6 个月的数据,每个月归档一次旧数据。
- 需要并行扫描——报表系统、数据仓库场景,经常要扫全量数据做聚合。
我的经验:如果你不确定要不要分区,先问自己三个问题:这张表超过 5000 万行了吗?查询条件里有没有固定的过滤字段?数据有明确的保留期限吗?三个都答「是」,那就大胆分区。
1.4 分区键的选择原则
分区键选错了,分区表还不如普通表。我曾经接手过一个项目,前人用 status 字段做分区键,结果 90% 的数据都在「已完成」分区里,其他分区几乎空的。分区裁剪完全失效,查询反而更慢。
选分区键,我建议遵循这几个原则:
- 高选择性——分区键的值分布要均匀。比如按月份分区,每个月的数据量差不多。别用性别、状态这种只有两三个值的字段。
- 查询条件中频繁出现——分区键要能出现在 WHERE 子句里,否则分区裁剪用不上。你想想看,如果按
order_date分区,但查询条件里从来不查日期,那分区就白做了。 - 数据量可预测——每个分区的数据量要相对稳定。比如按天分区,每天 100 万行,这样每个分区的性能表现一致。
- 尽量用时间字段——我个人的习惯是,80% 的分区表都用时间字段做分区键。时间天然有序,数据生命周期管理也方便。
避坑指南:我曾经见过有人用 UUID 做分区键,结果每次插入都跨分区,性能比普通表还差。分区键不要用随机性太强的字段,否则写入会变成「全分区扫描」。
1.5 分区表核心结构图
下面这张图,是我自己画的分区表核心结构。你可以看到逻辑表如何映射到物理分区,以及查询时分区裁剪的路径。
1.6 分区键选择决策表
最后,我整理了一张分区键选择决策表。你在设计分区表时,可以对照着选:
| 业务场景 | 推荐分区键 | 分区类型 | 注意事项 |
|---|---|---|---|
| 订单/交易流水 | order_date / created_at | RANGE 分区(按月) | 避免跨月查询,否则会扫多个分区 |
| 日志数据 | log_time | RANGE 分区(按天) | 每天数据量要均匀,避免某天暴增 |
| 用户数据 | user_id 哈希 | HASH 分区 | 分区数取 2 的幂,数据分布更均匀 |
| 地区数据 | region_code | LIST 分区 | 每个分区数据量不能差太多 |
| 物联网传感器 | device_id 哈希 + 时间 | 复合分区 | 先哈希再范围,兼顾写入和查询 |
我的建议:刚开始做分区表,先从 RANGE 分区入手,按时间分。这是最稳妥、最容易理解的方式。等你把分区裁剪、分区交换、分区合并这些操作都玩熟了,再考虑 HASH 或 LIST 分区。