如何循环执行Hive查询并使用循环变量?批量更新历史分区数据
当然可以实现循环执行的需求,而且还有更高效的替代方案,我来给你拆解清楚:
一、实现循环执行的两种方案
方案1:利用Hue Workflow的循环节点+参数化
Hue的Workflow支持循环节点,结合Coordinator的参数传递就能实现按日期循环:
- 第一步:在Coordinator配置中,先通过EL表达式生成需要处理的日期列表。比如当
run_date是2018-01-20、n=2时,生成[2018-01-20, 2018-01-19]这个数组。如果n是动态变量,可以用脚本提前生成日期列表并传入。 - 第二步:在Workflow中添加Loop节点,将日期数组设为循环变量,每次迭代把当前日期赋值给
${current_date}。 - 第三步:在Loop内部调用Hive Action,执行你的同步语句,把原有的
${date}替换成循环变量${current_date}:ALTER TABLE etable ADD IF NOT EXISTS PARTITION (date = '${current_date}') LOCATION 'path/date=${current_date}'; INSERT OVERWRITE TABLE itable partition(date = '${current_date}') SELECT * FROM etable WHERE date = '${current_date}';
方案2:用Shell脚本处理循环逻辑
如果Hue的循环节点配置起来比较繁琐,更灵活的方式是用Shell Action来实现循环:
- 在Coordinator中传递两个核心参数:
${run_date}(当前运行日期)和${n}(需要回溯的天数)。 - 在Workflow中添加Shell Action,编写脚本遍历n天的日期,逐个执行Hive语句:
#!/bin/bash run_date=$1 n=$2 for ((i=0; i<n; i++)) do # 计算当前要处理的日期 current_date=$(date -d "$run_date - $i days" +%Y-%m-%d) # 添加分区 hive -e "ALTER TABLE etable ADD IF NOT EXISTS PARTITION (date = '$current_date') LOCATION 'path/date=$current_date';" # 同步数据到内部表 hive -e "INSERT OVERWRITE TABLE itable partition(date = '$current_date') SELECT * FROM etable WHERE date = '$current_date';" done - 最后在Shell Action的参数配置里,传入
${run_date}和${n}即可。
二、更优方案:批量处理替代循环
循环执行n次Hive任务会带来额外的调度开销,其实可以用批量处理的方式一次性完成,效率更高:
1. 批量添加分区
可以用Shell脚本生成所有需要添加的分区语句,一次性执行:
#!/bin/bash run_date=$1 n=$2 for ((i=0; i<n; i++)) do current_date=$(date -d "$run_date - $i days" +%Y-%m-%d) echo "ALTER TABLE etable ADD IF NOT EXISTS PARTITION (date = '$current_date') LOCATION 'path/date=$current_date';" done | hive -f -
2. 批量同步数据
不需要循环执行INSERT,直接用一条Hive语句批量同步过去n天的数据:
INSERT OVERWRITE TABLE itable partition(date) SELECT * FROM etable WHERE date BETWEEN date_sub('${run_date}', ${n}-1) AND '${run_date}';
注意:Hive会自动根据SELECT结果中的
date字段值,将数据分发到itable对应的分区中,前提是itable的分区字段就是date,且SELECT结果的最后一列是date(或者和分区字段一一对应)。
这种批量处理的方式只需要执行2次操作(批量加分区+批量插入),避免了多次任务调度的开销,在数据量较大时优势很明显。
内容的提问来源于stack exchange,提问作者abhi195
相关产品推荐
相关产品推荐

