摘要:之前同事建表不太规范,没有建分区表,而是每天一个新的表,不同日期用表名后缀区分,每次想使用多个日期都需要大量的union all十分麻烦,而且大量union all操作又会占用大量driver内存,因此这些表是必然要改成分区表的,但是大量重复的操作去手动执行显然是不合适的,那么如何用shell脚本自动化执行呢?
#!/bin/bash
#脚本目标:将源表数据导入目标表中
#参数1:开始日期 参数2:结束日期
#源表(每天一个表): browser.detail_20200101等, browser.tidy_20200101等
#目标表(分区表):ods.ods_browser_detail(结尾有六个额外字段), ods.ods_browser_tidy
#ods_browser_detail字段过多且源表和目标表均为列式存储,查询和插入都会很慢
#操作的数据库:DB1源,DB2目标
DB1=browser
DB2=ods
#目标表名称
table1=ods_browser_detail
table2=ods_browser_tidy
#判断参数是否符合,如果第二个参数不为空并且两个参数长度都为8则进行下一步,否则退出
#&& [ `expr length $1` -eq 8 ] && [ `expr length $2` -eq 8 ]
if [ -n "$2" ] && [ ${#1} -eq 8 ] && [ ${#2} -eq 8 ]
#${#2}代表第二个参数的长度,其等价于`expr length $2`, expr代表求表达式的值,-n代表参数长度不为0时返回true,也可认为是判空语句
#此处其实可以不需要[ -n "$2" ]条件,但放在这里是为了提前做一下参数是否为空判断,加快执行效率
#当在脚本中需要执行一些指令并且将执行的结果赋给变量的时候需要使用“反引号”,此处无赋值可省略
then
#传入参数:开始日期,结束日期(都以20200101字符串形式传入)
begdate=$1
enddate=$2
else
echo "Args error!"
exit
fi
#将结束字符串转为标准日期格式2020-01-01,分区要用到,由于这个数值不会累加所以不进行循环更改
end=${enddate:0:4}"-"${enddate:4:2}"-"${enddate:6:2}
#外层循环while遍历每个表放入新表的固定分区
while [ "$begdate" -le "$enddate" ]
do
#将开始字符串转为标准日期格式2020-01-01
beg=${begdate:0:4}"-"${begdate:4:2}"-"${begdate:6:2}
#内层循环执行每天的两张表的导入
for table in ${table1} ${table2}
do
extra=''
#如果是第一张表
if [ ${table:12:1} = 'd' ]
then
#给额外六个字段赋空值
extra=', NULL, NULL, NULL, NULL, NULL, NULL'
elif [ "$begdate" -ge 20210201 ]
then
#第二个表数据只需导到20210131即可,因此直接跳过该循环
continue
fi
#核心hsql语句,set的是压缩
hive -e "
set hive.exec.compress.output=true;
set mapred.output.compress=true;
set mapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec;
set io.compression.codecs=org.apache.hadoop.io.compress.GzipCodec;
insert overwrite table ${DB2}.${table} partition(dt='$beg')
select *${extra} from ${DB1}.${table:12}_${begdate}"
done
#加上时分秒方便转换成时间戳
beg2=${beg}" 00:00:00"
beg_s=`date -d "$beg2" +%s`
#时间戳加86400增加一天
beg_s=`expr $beg_s + 86400`
#再转为标准时间,截取掉时分秒并去掉中间的-进入下次循环
begdate=`date -d @$beg_s "+%Y%m%d"`
done