分区布局是什么
Hive 表用目录表达分区:dt=2026-10-11 这样的目录名就是分区值,分区列属于元数据里的虚拟列,数据文件本身不重复存它。这样设计的收益是查询时能按目录做裁剪,只扫描相关分区;代价是「目录」和「元数据」两处要一致,往目录里放文件不等于表里就有了这个分区。理解这一点,分区相关的多数诡异现象都能解释清楚。
基本信息
| 目录布局 | /仓库/库.db/表/dt=2026-10-11/part-00000.parquet |
|---|---|
| 语义 | 分区列附加在目录上,数据文件不重复存分区列 |
| 维护手段 | ADD PARTITION / MSCK REPAIR TABLE 同步元数据 |
| 写入方式 | 静态分区需显式指定,动态分区按查询结果自动生成 |
| 适用场景 | Hive、Spark SQL、Presto/Trino 等按目录组织的表 |
| 常见约定 | 日期分区列统一命名 dt,避免 dt 与 date_str 混用 |
分区操作
分区操作
-- 手动登记单个分区
ALTER TABLE dwd_order ADD IF NOT EXISTS PARTITION (dt = '2026-10-11');
-- 扫描目录补登记缺失分区(Hive)
MSCK REPAIR TABLE dwd_order;
-- 查看分区列表与位置
SHOW PARTITIONS dwd_order;
DESCRIBE FORMATTED dwd_order PARTITION (dt='2026-10-11');
-- 动态分区写入前限制单次生成的分区数
SET hive.exec.max.dynamic.partitions = 500;
SET hive.exec.max.dynamic.partitions.pernode = 100;典型使用场景
- 按天增量落地:每天一个分区,查询直接裁剪到目标日期
- 补数与重刷:重写单个分区即可,不影响其他日期数据
- 历史归档:按分区做生命周期管理,过期分区整目录清理
- 跨表关联:分区键一致时可以把分区裁剪下推到两侧扫描
- 外部表接入:数据由其他系统写入目录,需要用 MSCK 或 ADD PARTITION 登记
目录与元数据不一致的表现
| 现象 | 原因 | 处理 |
|---|---|---|
| 数据在但 SELECT 查不到 | 分区未登记到元数据 | ADD PARTITION 或 MSCK REPAIR |
| 查询报分区不存在 | 目录名与元数据里的分区值不一致 | 核对目录名与分区列值 |
| 全表扫描特别慢 | 分区裁剪没生效 | 确认过滤条件用的是分区列本身 |
| 产生大量小分区 | 动态分区未限制,粒度过细 | 限制单次分区数并调整分区粒度 |
| 重写分区后旧数据还在 | 写入未覆盖原目录 | 使用动态分区覆盖或先删后写 |
动态分区写入默认上限较高,建议显式限制单次分区数,避免一次生成过多小分区。
分区列是虚拟列:SELECT * 通常不包含它,写入时也不能把分区列当作普通字段重复存储,否则容易出现「表里有列、目录里也有值」的不一致。