Hive 2.1.1字段和表註釋中文亂碼

##問題背景 通常咱們建立 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 employees 語句查看錶結構,發現字段註釋全是亂碼:數據庫

desc

desc formatted employees

使用 desc formatted employees 語句查看錶結構,發現表和字段註釋全是亂碼:apache

desc_formatted

show create table employees

最後使用 show create table employees 語句查看 employees 建表信息,也發現表和字段註釋全是亂碼:api

error-encode


##問題解決方案 ###修改Hive元數據庫編碼 當使用 MySQL 做爲 Hive 元數據庫的時候, Hive 元數據庫的字符集要設置成 latin1 default。app

使用 show create database hive 語句查看 hive 數據庫默認編碼。svn

hive-utf8

使用 alter database hive default character set latin1 將 hive 數據庫默認編碼改爲 latin1。oop

hive-latin

###修改相關表相關字段編碼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 編碼。

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]

相關文章
相關標籤/搜索