Hive 2.1.1字段和表注释中文乱码

##问题背景 一般我们创建 Hive 表时都需要给表和字段加上注释以便理解表的用途与字段的含义。但是往往在创建 Hive 表后查看表结构发现中文注释乱码,比较头疼。本文总结了一下针对这种情况的解决方案。


##问题重现 ###创建带中文注释的Hive表employees 使用 CREATE TABLE 语法创建一个带有中文注释的 Hive 表 employees:

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 employees 语句查看表结构,发现字段注释全是乱码:

desc

desc formatted employees

使用 desc formatted employees 语句查看表结构,发现表和字段注释全是乱码:

desc_formatted

show create table employees

最后使用 show create table employees 语句查看 employees 建表信息,也发现表和字段注释全是乱码:

error-encode


##问题解决方案 ###修改Hive元数据库编码 当使用 MySQL 作为 Hive 元数据库的时候, Hive 元数据库的字符集要设置成 latin1 default。

使用 show create database hive 语句查看 hive 数据库默认编码。

hive-utf8

使用 alter database hive default character set latin1 将 hive 数据库默认编码改成 latin1。

hive-latin

###修改相关表相关字段编码

以下语句是为了支持 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 编码。

desc-formatted_fix1

使用 show create table employees 语句查看建表信息,发现表和字段注释仍然都是乱码。 show_create_fix1

###打Patch Hive 表注释中文乱码是 Hive 的一个 bug, 详情参见 注释不能支持Unicode字符 。在 2.1.1 版本中还未解决这个bug, 所以需要自己手动打patch。链接中已经提供了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 编码。

desc-formatted_fix1

使用 show create table employees 语句查看建表信息, 发现表和字段注释都可以正常显示中文。

show_create_fix2

###解决desc formatted中文变成 Unicode 编码 还是需要打patch, 具体参见 https://issues.apache.org/jira/browse/HIVE-5682。链接中已经提供了patch文件:

patch2

方便做个记录,现将 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 查看表结构,发现表和字段注释都可以正常显示中文。

desc_formatted_fix2]

猜你喜欢

转载自blog.csdn.net/wypersist/article/details/80348272