对于分析人员来说,由于业务复杂,免不了会需要创建一些视图进行查询,然鹅,有时为了搞清楚视图牵涉到的表及业务关系,总免不了要去查看视图的创建细节的。好在 Hive 0.10 HIVE-967 起就对表/视图的 DDL 予以支持了,这部分 DDL 自然是存储在 Hive Metastore 中的。但实际使用 show create table 进行查询时(Hive 1.2.x),会发现以下两个比较讨厌的小问题:

  1. 无法显示中文注释(comment)
  2. 偶尔会出现中间的一些行为空白

以上这两个问题,第二个是非常影响用户对视图的理解的。通过一番搜索和本地测试可以发现引起这一现象的罪魁祸首竟然是 \t 特殊字符引起的!!!见 HIVE-4659Eric's Blog

从 Hive Metastore 对应的库表 hive.TBLS 中与视图 DDL 显示直接相关的字段我们可以发现有 VIEW_ORIGINAL_TEXTVIEW_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 编解码即可。