作为表哥、表姐,在实际工作中会创建大量的表,但由于每个人的开发习惯都有所不同,在表命名、字段命名和备注上不能形成一致的风格,导致后续数据库表的可读性差、数据使用效率低的问题,所以有必要对现成的数据库表字段的命名规范程度进行整理,继而输出一套用于规范命名规则的数据字典。
国际惯例,无论作哪些取数工作前,都需先列出结果数据的结构:
tbl_name(表名) | col(字段名) | comment(字段备注) |
---|---|---|
以 Hive 为例,批量查看表结构及备注的方法,最简单的就是:直接查询 Hive 元数据,在元数据库中可以通过 SQL 语句查询表结构、权限信息等各种表属性。
不过在大部分的情况下,我们都没有元数据相关的查询权限。但我们平时通过 desc tbl_name
或 show 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 -e
或 beeline -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