hive on tez为什么写表时,要写临时文件到hdfs目录
hive on tez为什么写表时,要写临时文件到hdfs目录
在Hive on Tez架构中,写表时将数据先写入HDFS临时目录,是保障数据一致性、支持容错重试、适配DAG计算模型的核心设计,本质是为了解决“计算过程不确定性”与“目标表数据完整性”之间的矛盾。以下从5个核心维度详细解释其原因:
1. 核心目标:保证写表操作的原子性
Hive写表(如INSERT INTO/OVERWRITE
)需要满足原子性——即操作要么“完全成功”(数据完整写入目标表),要么“完全失败”(目标表无任何脏数据),不允许“部分写入”的中间状态。
而直接写入目标表会存在致命问题:若计算过程中(如Tez任务崩溃、节点宕机)中断,目标表会残留不完整的“脏数据”,且无法回滚。
临时文件的解决方案:
- 计算过程中,Tez将结果先写入HDFS的临时目录(默认路径由
hive.exec.tmp.dir
配置,或目标表目录下的.tmp
子目录); - 待整个Tez DAG任务(所有Stage)完全执行成功后,通过HDFS的原子性rename操作,将临时目录的完整数据“移动”到目标表的正式目录(如
/user/hive/warehouse/table_name
); - 若任务失败,直接删除临时目录的部分数据,目标表完全不受影响。
关键原理:HDFS的
rename
是元数据级操作(仅修改目录引用,不移动实际数据块),具备天然原子性——要么rename成功(数据可见),要么失败(临时目录保留,目标表不变)。
2. 适配Tez的DAG模型:存储中间计算结果
Tez是基于“有向无环图(DAG)”的计算框架,Hive on Tez会将SQL解析为多个Stage(计算阶段) ,且Stage间存在依赖关系(如“先过滤→再聚合→最后Join”)。
这些Stage无法直接将结果写入目标表,必须通过临时文件传递数据:
- 前一个Stage的输出(如聚合后的中间结果),会先写入临时目录,作为下一个Stage的输入;
- 临时目录会按Stage ID、任务ID(Task ID)划分子目录(如
tmp/stage-1/_task0
),避免不同Stage的数据互相干扰; - 最终所有Stage执行完成后,才会将“最终结果”的临时目录合并并写入目标表。
例如:执行INSERT OVERWRITE table t SELECT a.id, sum(b.val) FROM a JOIN b ON a.id = b.id GROUP BY a.id
时,Tez会拆分为“Join Stage”→“Aggregation Stage”,两个Stage的中间结果均存储在临时目录,最后由Aggregation Stage的输出临时目录生成目标表数据。
3. 支持容错与重试,降低重复计算成本
Tez作为分布式计算框架,任务失败是常态(如节点宕机、内存溢出、网络波动)。临时文件的存在,能大幅降低失败后的重试成本:
- 若某个Stage失败,Tez仅需重试“失败的Stage”,而无需重新计算所有前置Stage——因为前置Stage的成功结果已保存在临时目录,可直接复用;
- 若没有临时文件,失败后需从头重新执行整个DAG任务,尤其对于大表计算,会造成巨大的资源浪费和时间延迟。
例如:一个包含5个Stage的任务,若第4个Stage失败,Tez可直接读取Stage 1-3的临时文件结果,仅重试Stage 4和5,而非重新执行1-5。
4. 处理数据格式转换与表结构适配
Hive支持多种存储格式(ORC、Parquet、TextFile、SequenceFile)和表类型(分区表、分桶表、外部表),写表时需要完成“计算结果→目标格式/结构”的转换,这个过程需依赖临时目录:
- 格式转换:计算结果默认是原始数据(如行存储),需在临时目录中完成“目标格式编码”(如ORC的列存储压缩、Parquet的页式存储),再写入目标表;
- 分区/分桶适配:若目标表是分区表(如按
dt=20240501
分区),临时目录会先按分区键创建子目录(tmp/dt=20240501
),确保数据写入正确分区;分桶表同理,临时目录会按分桶键哈希划分文件,避免最终分桶数据紊乱。
5. 隔离并发写操作,避免数据冲突
Hive虽默认不支持“多任务并发写同一张表”(需通过hive.support.concurrency
开启并发控制),但临时目录可在有限并发场景下隔离不同任务的数据:
- 不同写任务会生成独立的临时目录(如
tmp/task123
、tmp/task456
),各自处理数据,互不干扰; - 结合Hive的锁机制(如排他锁),任务获取锁后,再将临时目录原子rename到目标表,避免“多任务同时写目标表导致数据覆盖”的问题。
补充:临时目录的配置与清理
- 默认路径:临时文件默认存储在
hive.exec.tmp.dir
配置的路径(如/tmp/hive/${user.name}
),或目标表的Warehouse目录下的.tmp
子目录; - 自动清理:任务成功后,临时目录会被Hive自动删除;任务失败时,临时目录会保留(可通过
hive.exec.dynamic.partition.mode
等配置调整),用于调试失败原因; - 手动清理:若存在残留的临时文件(如Hive客户端崩溃导致),可通过
hdfs dfs -rm -r
手动删除临时目录,避免占用HDFS存储空间。
总结
Hive on Tez写表时使用HDFS临时目录,并非“额外步骤”,而是分布式计算场景下保障数据可靠性、计算高效性的必然设计。其核心价值可概括为:
- 用“临时存储+原子rename”保证数据原子性,避免脏数据;
- 用“中间结果落地”适配Tez的DAG模型,支持Stage间数据传递;
- 用“结果复用”降低容错重试成本,提升计算效率;
- 用“格式/结构适配”确保数据符合目标表规范。