对于分析人员来说,由于业务复杂,免不了会需要创建一些视图进行查询,然鹅,有时为了搞清楚视图牵涉到的表及业务关系,总免不了要去查看视图的创建细节的。好在 Hive 0.10 HIVE-967 起就对表/视图的 DDL 予以支持了,这部分 DDL 自然是存储在 Hive Metastore 中的。但实际使用 show create table
进行查询时(Hive 1.2.x),会发现以下两个比较讨厌的小问题:
- 无法显示中文注释(comment)
- 偶尔会出现中间的一些行为空白
以上这两个问题,第二个是非常影响用户对视图的理解的。通过一番搜索和本地测试可以发现引起这一现象的罪魁祸首竟然是 \t
特殊字符引起的!!!见 HIVE-4659 和 Eric's Blog
从 Hive Metastore 对应的库表 hive.TBLS
中与视图 DDL 显示直接相关的字段我们可以发现有 VIEW_ORIGINAL_TEXT
和 VIEW_EXPANDED_TEXT
. 直接查表可以发现 \t
均存储其中,所以从这可以推断在存储至 Metastore 时 Hive 并未做处理,最终显示为空白行是在查询输出的过程中产生的。
既然找到问题了,我们再想想怎么从源头上解决,从代码上可以跟到以下三个相关文件:
ql/src/java/org/apache/hadoop/hive/ql/exec/DDLTask.java
ql/src/java/org/apache/hadoop/hive/ql/metadata/formatting/MetaDataFormatUtils.java
metastore/src/gen/thrift/gen-javabean/org/apache/hadoop/hive/metastore/api/Table.java
其中 DDLTask.java#L1923`` 和 MetaDataFormatUtils.java
均含有调用视图创建文本的逻辑。
if (tbl.isView()) {
String createTab_stmt = "CREATE VIEW `" + tableName + "` AS " + tbl.getViewExpandedText();
outStream.writeBytes(createTab_stmt.toString());
简单粗暴的方法是在这里对输出的 \t
替换,这也是 Hive-4659 采取的方法。而从 Eric 的博客中可以发现 CDH 是在创建 DDL 存储至 Metastore 前去掉 \t
这种空白字符的。尽管这两种方法均可解决问题 2, 但这仍然并未从根本上解释问题的来源。从 tbl.getViewExpandedText()
继续跟下去可以发现这个方法是在 Table.java
中调用的,然后在这里面也没发现有对 \t
等特殊字符做特殊处理的步骤… 卒,这个问题后面再分析一下 Hive Metastore 源码才能给出根本原因了。
对于中文乱码的问题,我们可以在 toString 后加入 UTF-8 编解码即可。