##问题背景 通常咱们建立 Hive 表时都须要给表和字段加上注释以便理解表的用途与字段的含义。可是每每在建立 Hive 表后查看表结构发现中文注释乱码,比较头疼。本文总结了一下针对这种状况的解决方案。java
##问题重现 ###建立带中文注释的Hive表employees 使用 CREATE TABLE 语法建立一个带有中文注释的 Hive 表 employees:git
CREATE TABLE IF NOT EXISTS employees ( name STRING COMMENT '姓名', salary FLOAT COMMENT '薪水', subordinates ARRAY<STRING> COMMENT '下属', deductions MAP<STRING, FLOAT> COMMENT '扣除金额', address STRUCT<street:STRING, city:STRING, state:STRING, zip:INT> COMMENT '住址' ) COMMENT '员工表' ROW FORMAT DELIMITED FIELDS TERMINATED BY '\001' COLLECTION ITEMS TERMINATED BY '\002' MAP KEYS TERMINATED BY '\003' LINES TERMINATED BY '\n' STORED AS TEXTFILE;
使用 desc employees 语句查看表结构,发现字段注释全是乱码:数据库
使用 desc formatted employees 语句查看表结构,发现表和字段注释全是乱码:apache
最后使用 show create table employees 语句查看 employees 建表信息,也发现表和字段注释全是乱码:api
##问题解决方案 ###修改Hive元数据库编码 当使用 MySQL 做为 Hive 元数据库的时候, Hive 元数据库的字符集要设置成 latin1 default。app
使用 show create database hive 语句查看 hive 数据库默认编码。svn
使用 alter database hive default character set latin1 将 hive 数据库默认编码改为 latin1。oop
###修改相关表相关字段编码ui
如下语句是为了支持 Hive 建表时插入中文注释编码
alter table COLUMNS_V2 modify column COMMENT varchar(256) character set utf8; alter table TABLE_PARAMS modify column PARAM_VALUE varchar(4000) character set utf8; alter table PARTITION_PARAMS modify column PARAM_VALUE varchar(4000) character set utf8; alter table PARTITION_KEYS modify column PKEY_COMMENT varchar(4000) character set utf8; alter table INDEX_PARAMS modify column PARAM_VALUE varchar(4000) character set utf8;
###验证结果 从新建立 employees 表。
使用 desc employees 语句查看表结构,发现字段注释能够正常显示中文。
使用 desc formatted employees 语句查看表结构, 发现字段注释能够正常显示中文,可是表注释显示的虽然不是乱码,但倒是 Unicode 编码。
使用 show create table employees 语句查看建表信息,发现表和字段注释仍然都是乱码。
###打Patch Hive 表注释中文乱码是 Hive 的一个 bug, 详情参见 注释不能支持Unicode字符 。在 2.1.1 版本中还未解决这个bug, 因此须要本身手动打patch。连接中已经提供了patch文件:
方便作个记录,现将 HIVE-11837.1.patch 内容粘贴出来:
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/exec/DDLTask.java b/ql/src/java/org/apache/hadoop/hive/ql/exec/DDLTask.java index 6fca9f7ec86574a6053af3672c551c6a63aa4870..661367f27b69f9796140808eda53a3bbcdcbdb11 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/exec/DDLTask.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/exec/DDLTask.java @@ -2048,7 +2048,7 @@ private int showCreateTable(Hive db, DataOutputStream outStream, String tableNam if (tbl.isView()) { String createTab_stmt = "CREATE VIEW `" + tableName + "` AS " + tbl.getViewExpandedText(); - outStream.writeBytes(createTab_stmt.toString()); + outStream.write(createTab_stmt.toString().getBytes("UTF-8")); return 0; } @@ -2196,7 +2196,7 @@ else if (sortCol.getOrder() == BaseSemanticAnalyzer.HIVE_COLUMN_ORDER_DESC) { } createTab_stmt.add(TBL_PROPERTIES, tbl_properties); - outStream.writeBytes(createTab_stmt.render()); + outStream.write(createTab_stmt.render().getBytes("UTF-8")); } catch (IOException e) { LOG.info("show create table: " + stringifyException(e)); return 1;
前面的 + 号表示须要新加的代码,- 号表示须要删除的代码。
接下来下载 Hive 2.1.1 源码包 apache-hive-2.1.1-src.tar.gz,而后解压。修改 DDLTask.java 源码,接着使用如下Maven命令进行编译打包。
mvn clean package -DskipTests=true
最后,将新生成的 hive-exec-2.1.1.jar 文件替换掉 $HIVE_HOME/lib 目录下的 hive-exec-2.1.1.jar 文件。
重启 Hive 客户端 ,而后从新建立 employees 表。
使用 desc employees 语句查看表结构,发现字段注释能够正常显示中文。
使用 desc formatted employees 语句查看表结构, 发现字段注释能够正常显示中文,可是表注释显示的虽然不是乱码,但倒是 Unicode 编码。
使用 show create table employees 语句查看建表信息, 发现表和字段注释均可以正常显示中文。
###解决desc formatted中文变成 Unicode 编码 仍是须要打patch, 具体参见 https://issues.apache.org/jira/browse/HIVE-5682。连接中已经提供了patch文件:
方便作个记录,现将 HIVE-5682.patch 内容粘贴出来:
### Eclipse Workspace Patch 1.0 #P hive-0.12.0-jd-svn Index: ql/src/java/org/apache/hadoop/hive/ql/metadata/formatting/MetaDataFormatUtils.java =================================================================== --- ql/src/java/org/apache/hadoop/hive/ql/metadata/formatting/MetaDataFormatUtils.java (revision 29) +++ ql/src/java/org/apache/hadoop/hive/ql/metadata/formatting/MetaDataFormatUtils.java (working copy) @@ -28,6 +28,8 @@ import java.util.Set; import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.hadoop.hive.conf.HiveConf; import org.apache.hadoop.hive.metastore.TableType; import org.apache.hadoop.hive.metastore.api.FieldSchema; @@ -47,7 +49,7 @@ * */ public final class MetaDataFormatUtils { - + private static final Log LOG = LogFactory.getLog("org.apache.hadoop.hive.ql.metadata.formatting.MetaDataFormatUtils"); public static final String FIELD_DELIM = "\t"; public static final String LINE_DELIM = "\n"; @@ -262,10 +264,20 @@ private static void displayAllParameters(Map<String, String> params, StringBuilder tableInfo) { List<String> keys = new ArrayList<String>(params.keySet()); + String value = null; Collections.sort(keys); for (String key : keys) { tableInfo.append(FIELD_DELIM); // Ensures all params are indented. - formatOutput(key, StringEscapeUtils.escapeJava(params.get(key)), tableInfo); + value = params.get(key); + LOG.info(">>lvxin displayAllParameters:key="+key+";params.get(key)="+params.get(key)); + if("comment".equals(key)&& null!=value && value.getBytes().length!=key.length()) + { + formatOutput(key, value, tableInfo); + } + else + { + formatOutput(key, StringEscapeUtils.escapeJava(value), tableInfo); + } } }
前面的 + 号表示须要新加的代码,- 号表示须要删除的代码。
一样的修改 MetaDataFormatUtils 源码,接着使用如下Maven命令进行编译打包。
mvn clean package -DskipTests=true
最后,将新生成的 hive-exec-2.1.1.jar 文件替换掉 $HIVE_HOME/lib 目录下的 hive-exec-2.1.1.jar 文件。
###验证结果 重启 Hive 客户端。
使用 desc formatted employees 查看表结构,发现表和字段注释均可以正常显示中文。
]