最近遇到的一个工作任务。由于公司集群不支持使用hive命令,只能使用beeline命令。
通过beeline -e 或 beeline -f 导出的结果,会包含一些其他多余的信息,不好过滤。
同时beeline -e 只能跟一条sql语句。
于是使用spark-sql来完成脚本编写。
第一版
spark-sql -e "use test ; show tables;" > tables.txt
cat tables.txt | awk '{print$2}' |while read eachline
#由于用spark-sql查询出的表信息包含三列,分别是库名 表名 false 用awk筛选出第二列的表名。
do
spark-sql -e "use test ; show create table $eachline;" >>tablesDDL.sql
echo ";" >> tablesDDL.sql
#在每条建表语句后追加分号,以便用于批量建表。
done
问题:执行速度非常慢,每循环一次,就会启停一次spark-sql客户端,浪费时间和集群资源。
优化执行脚本:
将循环产生的查询建表语句的sql先重定向到txt文件中,再使用spark-sql -f sql文件 的方式。
就只需要启动一次spark-sql客户端。
spark-sql -e "use $1 ; show tables;" > tables.txt
cat tables.txt | awk '{print$2}' |while read eachline
do
echo "show create table $1.$eachline;" >>CreateTable.hql
done
#kinit -kt **** ****
spark-sql -f CreateTable.hql > tablesDDL.hql
产生一个新的问题:每条建表语句间的分号就只能手动添加了???
于是,想到了用sed -i "s/^)$/);/g" 去匹配每条sql语句结束的)并替换为);。
但是发现我想多了,仔细查看sql语句,并不是只有每条sql语句结束了的最后单行为),在中间还有一处也是
单行一个).
怎么办呢? 想了半天,又想到一种方法可行。观察了各建表语句,发现了一条规律就是,
每条语句结束的上一行都是'numRows' = '-1'。于是可以利用sed命令打印出匹配该内容的行数,
然后再利用awk的算法运算去+1行,就得到了每条建表语句结束的那一行的行数,最后再用sed -i去匹配替换指定的行的内容。
搞定收工。
sed -n -e "/'numRows' = '-1'/=" tablesDDL.hql | awk '{print$1+1}' | while read line
do
sed -i "${line}s/)/);/g" tablesDDL.hql
done
虽然这只是一个简单的脚本,但发现了一些问题,就应该去一步步地思考如何解决。
这最重要的还是这种思考问题解决问题的思维方式。加油!!!