##問題背景 通常咱們建立 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 查看錶結構,發現表和字段註釋均可以正常顯示中文。
]