Shell 批量导出 Hive 表的字段及备注

作为表哥、表姐,在实际工作中会创建大量的表,但由于每个人的开发习惯都有所不同,在表命名、字段命名和备注上不能形成一致的风格,导致后续数据库表的可读性差、数据使用效率低的问题,所以有必要对现成的数据库表字段的命名规范程度进行整理,继而输出一套用于规范命名规则的数据字典。

国际惯例,无论作哪些取数工作前,都需先列出结果数据的结构:

tbl_name(表名) col(字段名) comment(字段备注)

以 Hive 为例,批量查看表结构及备注的方法,最简单的就是:直接查询 Hive 元数据,在元数据库中可以通过 SQL 语句查询表结构、权限信息等各种表属性。

不过在大部分的情况下,我们都没有元数据相关的查询权限。但我们平时通过 desc tbl_nameshow create table tbl_name 语句查询到表里字段名和备注信息,因此我们可以借助 shell 脚本,把上述语句的查询结果存放(重定向)到临时文件,接下来就是文本处理的工作了,然后就能得到我们想要的信息了。

我们将任务拆解一下:

一、构建 Hive 连接串

官方提供的 Hive 的连接方式:

1)CLI(Command-Line Interface) 连接,我们输入 hive 命令执行时,相当于在启动的时候执行 hive --service cli,但同时我们也会看到这样的 warning(Hive CLI is deprecated and migration to Beeline is recommended.),官方更建议我们使用 Beeline 进行连接。

2)Beeline 连接,Beeline 支持嵌入模式(embedded mode)和远程模式(remote mode),可基于 jdbc 串进行连接到独立的 HiveServer2 进程上

Beeline 是官方更推荐使用的工具,而且在命令行上键入 beeline -H 查看到帮助文档时,各参数的定义都写得很明确了,我们可以通过 beeline -ebeeline -f 命令执行 SQL 语句。

beeline -n ${username} -p ${password}  -u 'jdbc:hive2://server1,server2,server3/;serviceDiscoveryMode=zooKeeper;' -e "DESC tmp.tmp_tbl;"
  • -n:设置 beeline 连接的用户名
  • -p:设置 beeline 连接的密码
  • -u:设置 JDBC 连接串
  • -e:设置要执行的 SQL 语句

通过以上参数设置,我们便可以 Linux 命令行执行 Hive SQL 语句了。

二、修饰 Hive 结果输出格式

beeline 默认输出结果会包含表头、表格线以及调试信息,我们可以在实际执行 beeline 指令的时候,修改部分参数的赋值,从而改变输出结果的格式。

beeline --showHeader=false --verbose=false --showWarnings=false --outputformat=tsv -n ${username} -p ${password}  -u 'jdbc:hive2://server1,server2,server3/;serviceDiscoveryMode=zooKeeper;' -e "DESC tmp.tmp_tbl;"
  • --showHeader:是否显示查询结果的列名
  • --verbose:是否显示详细错误信息和调试信息
  • --showWarnings:是否显示警告

改动参数后,输出结果虽然可读性比原来的要差,但简化后的结果更方便后续的数据处理。然后我们对该连接串封装成 shell 函数,并将 -e 部分设置为传参的样式,这样往后只需要把要执行的 SQL 语句作为该函数的参数即可,方便重复使用。

function ExecHive()
{
    beeline --showHeader=false --verbose=false --showWarnings=false --outputformat=tsv -n ${username} -p ${password}  -u 'jdbc:hive2://server1,server2,server3/;serviceDiscoveryMode=zooKeeper;' -e $1
}

三、遍历所有的表及字段信息

我们可以通过 show tables; 来获得库中所有表的名单,然后对名单上的每个表查看其 desc 信息,就能获得每个表的字段及其注释信息。

databases=('db1' 'db2') # 要遍历的数据库
for database in ${databases[@]}
do
{
    # 导出所有的表
    ExecHive "use $database ;  show tables ;" | sed s/\'//g > /home/result/$database
    rm /home/result/desc_tbl/$database

    # 查询每个表的 desc 信息
    for table in `cat /home/result/$database`
    do
        ExecHive  "desc $database.$table ;"  >> /home/result/desc_tbl/$database
    done
}

每一个导出环节,都需要检查一些输出结果的格式,如 show tables 那一步导出的表名会带有引号,这可能会影响到后面查询 desc 信息的步骤,所以可以先通过 sed 工具对引号进行处理。

另外,在 Hive 中查看 desc 信息时,会附上表的分区信息(Partition Information),而这部分信息中会包括分区字段,并与上面的字段信息重复,需要去掉,因此可以通过「管道」将结果传递给 awk 进行行筛选——保留 Partition Information 之前的行。

# 定义 line 变量,
line=`ExecHive  "desc $database.$table ;" | awk '/# Partition Information/{print NR}'`
ExecHive  "desc $database.$table ;" | awk -v line=${line} -v database=$database -v table=$table '{if(NR> /home/result/desc_tbl/$database

完整代码

#!/bin/bash

function ExecHive()
{
    beeline --showHeader=false --verbose=false --showWarnings=false --outputformat=tsv -n ${username} -p ${password}  -u 'jdbc:hive2://server1,server2,server3/;serviceDiscoveryMode=zooKeeper;' -e $1
}

databases=('ad' 'ad_da')
for database in ${databases[@]}
do
  {
      ExecHive "use $database ;  show tables ;" | sed s/\'//g > /home/result/$database
      rm /home/result/desc_tbl/$database
      for table in `cat /home/result/$database`
      do
      {
        # 获得分区信息的行号
        line=`ExecHive  "desc $database.$table ;" | awk '/# Partition Information/{print NR}'`
        # 通过管道将 desc 的查询结果传递到 awk,并通过 awk -v 设置变量,规整结果输出
        ExecHive  "desc $database.$table ;" | awk -v line=${line} -v database=$database -v table=$table '{if(NR> /home/result/desc_tbl/$database
      }
      done
  }
done

你可能感兴趣的:(Shell 批量导出 Hive 表的字段及备注)