Hive中文注释乱码解决方案
本文來自網(wǎng)易云社區(qū)
作者:王潘安
快速解決方法
目前的hive客戶端在執(zhí)行desc tablexxx和show create table xxx命令的時候,字段的中文注釋會出現(xiàn)亂碼情況,如(????)。在使用 ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' 建表的時候,注釋則會出現(xiàn)from deserializer。以下幾個步驟可以幫你快速解決這些問題:
1.首先在hive客戶端的conf目錄下找到hive-site.xml配置文件,查詢本機hive所連接的metastore地址。例如:
????????<property><name>javax.jdo.option.ConnectionURL</name><value>jdbc:mysql://10.120.xxx.xxx:3306/hive_study</value></property>連接該數(shù)據(jù)庫。找到表COLUMNS_V2并查詢其中的字段。如果為類似以下的亂碼:
?|???952?|?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????|?in_l_notice_mail?????????????|?string?????????????|??????????14?| |???952?|?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????|?live_course_notice_mail??????|?string?????????????|??????????22?| |???952?|?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????|?mark_best_reply??????????????|?string?????????????|???????????4?| |???952?|?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????|?platform_notice_mail?????????|?string?????????????|??????????13?| |???952?|?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????|?question_answered????????????|?string?????????????|???????????3?| |???952?|?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????|?question_digged??????????????|?string?????????????|???????????6?| |???952?|?sns?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????|?sns_friends_attend???????????|?string?????????????|??????????20?| |???952?|?sns?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????|?sns_new_fans?????????????????|?string?????????????|??????????21?| |???952?|?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????|?study_plan_notice????????????|?string?????????????|??????????15?| |???952?|???id則對數(shù)據(jù)庫做如下設(shè)置:
??//修改字段注釋字符集 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; //修改分區(qū)注釋字符集 alter?table?PARTITION_KEYS?modify?column?PKEY_COMMENT?varchar(4000)?character?set?utf8;并且重新建hive表(不是metastore的表)。如果COLUMNS_V2中的數(shù)據(jù)不為亂碼,則不用做任何操作,跳過此步。
2.將本文附件中的兩個jar包替換到hive客戶端的lib目錄中。
3.重啟hive客戶端,測試一下效果。
解決過程及BUG原因解釋
1.準備工作
首先在自己電腦上部署HADOOP,HIVE環(huán)境。下載hive和Hive-JSON-Serde,鏈接:https://github.com/apache/hive https://github.com/rcongiu/Hive-JSON-Serde 確保可以運行起來。然后就要做好以下準備:
1.找到hive運行時打印的log的位置。如果沒有配置如下屬性,那就是默認位置:
???????<property><name>hive.exec.local.scratchdir</name><value>${system:java.io.tmpdir}/${system:user.name}</value><description>Local?scratch?space?for?Hive?jobs</description></property>以云課堂為例,就是放在/tmp/study目錄下,日志會記錄在hive.log中。
2.準備好調(diào)試環(huán)境。找到hadoop的目錄,在bin目錄下找到hadoop這個可執(zhí)行的命令,打開它,找到如下一段代碼:
??????if?[?"$COMMAND"?=?"fs"?]?;?then.apache.hadoop.fs.FsShellelif?[?"$COMMAND"?=?"version"?]?;?then.apache.hadoop.util.VersionInfoelif?[?"$COMMAND"?=?"jar"?]?;?then.apache.hadoop.util.RunJarelif?[?"$COMMAND"?=?"key"?]?;?then.apache.hadoop.crypto.key.KeyShellelif?[?"$COMMAND"?=?"checknative"?]?;?then.apache.hadoop.util.NativeLibraryChecker把他改為:
????if?[?"$COMMAND"?=?"fs"?]?;?then.apache.hadoop.fs.FsShellelif?[?"$COMMAND"?=?"version"?]?;?then.apache.hadoop.util.VersionInfoelif?[?"$COMMAND"?=?"jar"?]?;?thenif?!?echo?"$HADOOP_CLIENT_OPTS"|fgrep?'dt_socket'?;?thenHADOOP_CLIENT_OPTS="$HADOOP_CLIENT_OPTS??-Xdebug?-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8765"fiHIVE_DEBUG_RECURSIVE=yHIVE_MAIN_CLIENT_DEBUG_OPTS="suspend=n,address=8765"HIVE_CHILD_CLIENT_DEBUG_OPTS="suspend=y,address=8766"export?HADOOP_CLIENT_OPTS?HIVE_CHILD_CLIENT_DEBUG_OPTS?HIVE_DEBUG_RECURSIVE?HIVE_MAIN_CLIENT_DEBUG_OPTS.apache.hadoop.util.RunJarelif?[?"$COMMAND"?=?"key"?]?;?then.apache.hadoop.crypto.key.KeyShellelif?[?"$COMMAND"?=?"checknative"?]?;?then.apache.hadoop.util.NativeLibraryChecker這樣,就打開了端口號為8765的遠程調(diào)試端口
具體為啥這樣設(shè)置,參考這篇博客:http://blog.csdn.net/wisgood/article/details/38047921
2.查找BUG
首先聲明,以下所有的調(diào)試都是基于hive 1.2.1版本和json-serde 1.3.6的版本。
Hive客戶端的啟動是在源碼的cli目錄下的org.apache.hadoop.hive.cli包中的CliDriver類中,它又具體去調(diào)用了ql目錄下的org.apache.hadoop.hive.ql包中的Driver類。因此,我們在IDE中只需要引入ql目錄下的maven工程即可。
打開Driver類,找到它的run方法,這便是hive命令執(zhí)行的函數(shù)入口。在run方法中,主要調(diào)用的就是runInternal方法。而runInternal方法中主要就是調(diào)用了compileInternal和execute方法,也就是編譯命令和執(zhí)行命令兩部分。
編譯階段
首先我們看看compile階段干了些啥,通過跟蹤compileInternel方法,我們可以知道,它最終調(diào)用的是compile方法。這個方法主要是用來生成執(zhí)行計劃樹的。首先解析出樹形結(jié)構(gòu),這段代碼慎重跟蹤下去,水太深,會游泳的可以下去看看:
???????ParseDriver?pd?=?new?ParseDriver();ASTNode?tree?=?pd.parse(command,?ctx);然后進行語義分析:
?BaseSemanticAnalyzer?sem?=?SemanticAnalyzerFactory.get(conf,?tree);sem.analyze(tree,?ctx);接著生成執(zhí)行計劃:
???????plan?=?new?QueryPlan(queryStr,?sem,?perfLogger.getStartTime(PerfLogger.DRIVER_RUN),?queryId,SessionState.get().getCommandType());最后還要拿到返回結(jié)果的模板,也就是說明返回值的樣子:
?schema?=?getSchema(sem,?conf);在這個過程中,我們重點關(guān)注的是語義分析和返回值模板的情況。可以看到,語義分析首先通過工廠返回了一個BaseSemanticAnalyzer,這是一個父類,而我們執(zhí)行類似show create table xxx的時候,它實際執(zhí)行的是它的一個子類DDLSemanticAnalyzer中的analyzeInternal方法。我們?nèi)タ催@個方法,發(fā)現(xiàn)它是一堆switch case,我們在其中找到如下代碼:
?????case?HiveParser.TOK_SHOW_CREATETABLE:?????ctx.setResFile(ctx.getLocalTmpPath());analyzeShowCreateTable(ast);break;跟到analyzeShowCreateTable方法中去,發(fā)現(xiàn)有這樣一段代碼:
?Table?tab?=?getTable(tableName);好激動,貌似拿到了表信息,我們把斷點打在這,并且進行調(diào)試,看看這個tab變量里面究竟有啥:?
發(fā)現(xiàn)什么表信息都有,的確去metastore庫里面拿了東西,注意:我這里的comment是???這樣的亂碼是因為我的metastore里面的表的編碼格式?jīng)]改。所以到目前為止,hive的代碼是正常的。
在analyzeShowCreateTable方法中,還有幾個要注意的點,一個是:
?showCreateTblDesc?=?new?ShowCreateTableDesc(tableName,?ctx.getResFile().toString());一個是:
?setFetchTask(createFetchTask(showCreateTblDesc.getSchema()));還有一個:
?????rootTasks.add(TaskFactory.get(new?DDLWork(getInputs(),?getOutputs(),?showCreateTblDesc),?conf));首先看ShowCreateTableDesc類里面有什么,發(fā)現(xiàn)有這樣一個字符串常量:
?private?static?final?String?schema?=?"createtab_stmt#string";通過對比這個類同包中的其他類的schema常量,比如DescTableDesc類:
private?static?final?String?schema?=?"col_name,data_type,comment#string:string:string";不難猜出,這個就是定義輸出結(jié)果的樣子和每個結(jié)構(gòu)的類型的常量。接著我們看createFetchTask方法,在這個里面,它把上面說的字符串schema解析出來放到了Properties配置中:
????String[]?colTypes?=?schema.split("#");prop.setProperty("columns",?colTypes[0]);prop.setProperty("columns.types",?colTypes[1]);prop.setProperty(serdeConstants.SERIALIZATION_LIB,?LazySimpleSerDe.class.getName());看到這段代碼,簡直點燃了我的興奮點!我們的問題不就是字段注釋亂碼嗎?(劇透一下,如果你不給hive傳注釋信息,那么hive就給你寫個from deserializer)這里定義了字段名字,字段類型以及序列化類,但是沒有定義字段注釋!難道問題就出在這?然而仔細想想,這個地方就是誤導你的。因為在這個階段雖然已經(jīng)在metastore中獲取了table信息,然而這個階段仍然是編譯階段,具體的命令還沒有執(zhí)行。另外在property中,設(shè)置的都是常量,所以它更不可能是最后的返回結(jié)果。其實它的作用是描述這個模板的類型以及序列化方法,而不是用來描述最后的結(jié)果的。
最后我們再來看rootTasks.add方法干了什么,可以發(fā)現(xiàn),TaskFactory通過get方法產(chǎn)生了一個task,放到了task的序列中,這個get方法通過你傳入進來的work類型,找到相應(yīng)的task類型,并且通過java的反射機制創(chuàng)建一個task實例。在這里,我們傳入的是一個DDLWork,因此它會創(chuàng)建一個DDLTask。我們要牢記這個DDLTask類,因為后面的執(zhí)行過程中,就是去執(zhí)行它!
網(wǎng)易云免費體驗館,0成本體驗20+款云產(chǎn)品!
更多網(wǎng)易研發(fā)、產(chǎn)品、運營經(jīng)驗分享請訪問網(wǎng)易云社區(qū)。
相關(guān)文章:
【推薦】?如何實現(xiàn)最佳的跨平臺游戲體驗呢?
【推薦】?最小化局部邊際的合并聚類算法(中篇)
總結(jié)
以上是生活随笔為你收集整理的Hive中文注释乱码解决方案的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hyper-v NAT网络
- 下一篇: CSAPC08台湾邀请赛_T1_skyl