动态分区写入
动态分区让 Hive 或 Spark 按 SELECT 末尾的分区列自动生成目标分区,不用为每个分区写一条 INSERT。使用前要开启开关、设置为 nonstrict 模式,并限制单次最大分区数。分区数一旦失控,会同时产生大量小文件并压垮元数据服务,这是动态分区最常见的生产事故。
基本信息
| 开关 | hive.exec.dynamic.partition |
|---|---|
| 模式 | nonstrict,需显式设置 |
| 上限 | hive.exec.max.dynamic.partitions |
| 分区列位置 | SELECT 的最后若干列 |
| 风险 | 分区爆炸与小文件 |
典型使用场景
- 目标分区集合事先不确定:一次写入多个日期或多个业务线分区
- 例行调度按数据日期写入:避免为每个分区拼一条 INSERT
- 补数回刷:只对受影响日期重跑,其他分区保持不动
- 写入前评估分区数量,超过阈值时按日期拆分任务分批写入
- 排查写入失败:先确认是否触发分区数量上限,再检查分区列顺序
动态分区写入
动态分区写入
set hive.exec.dynamic.partition=true; -- 开启动态分区
set hive.exec.dynamic.partition.mode=nonstrict; -- 允许全动态写入
set hive.exec.max.dynamic.partitions=2000; -- 任务级分区上限
set hive.exec.max.dynamic.partitions.pernode=500; -- 单节点上限
INSERT OVERWRITE TABLE dwd_trade_order_di PARTITION (dt) -- 分区列写在 SELECT 末尾
SELECT order_id, pay_amt, dt
FROM stg_order;关键参数
| 参数 | 作用 | 建议取值 |
|---|---|---|
| hive.exec.dynamic.partition | 动态分区总开关 | true |
| dynamic.partition.mode | 是否允许全动态 | nonstrict |
| max.dynamic.partitions | 单任务分区上限 | 按集群容量设定 |
| max.dynamic.partitions.pernode | 单节点分区上限 | 避免单节点压力过大 |
动态分区列必须是 SELECT 的最后若干列,顺序错位不会报错,但数据会被写进错误分区,事后只能按分区整段回刷。
Spark 写分区表时也有对应行为:spark.sql.sources.partitionOverwriteMode 决定覆盖是整表还是按分区,模式选错会把整表重写,分区列需在末尾的约束与 Hive 一致。
动态分区适合目标分区不确定的写入;当分区集合已知且数量不大时,改用静态分区逐分区写入更可控:出错范围限于单个分区,也便于重跑与校验。
动态分区与单一 reduce 组合会退化成单任务写入,数据量大时任务超时;需要并行写入时按分区键设置合理的 reduce 数或改用 Spark 写出。