當前位置:編程學習大全網 - 源碼下載 - 如何進行Hive debug

如何進行Hive debug

本文主要總結我在使用HQL執行Query類操作時用到的DEBUG方法,主要有這麽幾板斧:

打開hive DEBUG日誌

explain

查看plan.xml

使用IDE遠程Debug

下面壹壹簡單說明下方法,例子先不舉了,壹時手頭沒特合適的CASE。

打開hive DEBUG日誌

這個比較基本,也很容易操作。出問題時先打開,興許有些有用的信息。另外我們自己的UDF或SerDe裏也可以輸出些DEBUG日誌,方便定位問題:

hive -hiveconf hive.root.logger=DEBUG,console

explain

即在HQL前加上EXPLAIN,比如

EXPLAIN SELECT * FROM ...

不過這個在查錯誤的時候用處不大,我還沒用它定位到什麽BUG。不過在查壹些性能問題,或者查看下hive到MR任務的執行過程時會用得著

查看plan.xml

先得說下hive的執行過程。大體上是這樣的:

hive 客戶端(壹般是hive cli,入口類為CliDriver)把HQL翻譯成MR執行計劃(Operator樹)並序列化到 plan.xml

plan.xml 上傳到hdfs上

hive 客戶端新起壹進程,提交MapReduce程序,其入口類為ExecDriver,ExecDriver的Mapper會在setup階段讀取plan.xml,反序列化成Operator樹結構,然後執行。

所以plan.xml精確的描述了MR程序具體的執行過程,而且xml文件層次清楚,比explain輸出更豐富的信息,也很易讀。MR執行計劃很少出問題,但我們可以借助plan.xml排除壹些懷疑會出問題的點,比如確認是翻譯階段的問題,還是MR執行階段的問題。

曾經有壹次定位UDF使用的BUG,最開始懷疑是hive生成MR執行計劃出錯了,但通過查看plan.xml,我們確認翻譯階段沒問題。進而開始使用終極手段來看問題:IDE遠程DEBUG,單步跟蹤,這個我們稍後說。

查看plan.xml的方法,有點trick。HIVE cli在生成 plan.xml時,會打印日誌:

Generating plan file <some_temp_dir>/plan.xml

但hive 任務執行完畢時,會把它刪掉。所以妳得手快,或者想辦法讓hql跑的時間長點,比如sleep壹下之類。如果有什麽參數可以讓hive不刪plan文件,留言給我, 先行謝過。

使用IDE遠程DEBUG

之所以說是終極手段,有兩個意思:

如果上面的幾個手段都定位不到問題,這個八成能幫妳找到問題,反正我屢試不爽

用起來著實得費些力氣:

首先,最好能用hive本地模式復現BUG

否則還得找到具體執行此任務的Hadoop節點IP,更麻煩了。 啟用本地模式的方法是:

# hadoop0.20

SET mapred.job.tracker=local;

# hadoop 1及以上版本

set mapreduce.framework.name=local;

有壹個參數容易混淆:

SET hive.exec.mode.local.auto=false;

這實際上是hive的壹個優化,即在hive認為合適的時候,自動啟用local模式以更快的計算(數據量比較小的時候有用)。所以設置此參數,不壹定會以local模式運行。

為JVM 添加遠程調試參數

參數比較簡單,很多文章裏都有介紹(不過我覺得IBM這篇最好):

-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8765

suspend=y 是為了讓我們有機會把IDE attach到被調試進程上,否則又是個拼手快的活兒了。

麻煩之處在於,從啟動hive到運行MR程序過程中,需要啟動兩個JVM(也有只啟動壹個的情況,稍後再說):

hive cli需要壹個JVM,入口類CliDriver

提MR程序需要壹個JVM,入口類ExecDriver

壹般我們希望調試MR階段的代碼,所以我們需要保證在啟動第壹個JVM時,不監聽調試端口,只在第二個JVM上加上述參數。或者至少兩階段使用不同的端口,否則第二個JVM端口沖突就無法啟動了。

hive啟動CliDriver和ExecDriver都通過 ‘hadoop jar’來啟動。所以添加JVM參數可以通過HADOOP_CLIENT_OPTS環境變量添加, 但是, 直接export HADOOP_CLIENT_OPTS 是不行的,因為hive在 調用hadoop jar之前,要調用hadoop version 來確定版本,HADOOP_CLIENT_OPTS對hadoop version同樣生效,所以只能改hadoop啟動腳本了,通常是/usr/lib/hadoop/bin/hadoop,要在這段代碼附件設置:

...

elif [ "$COMMAND" = "jar" ] ; then

# 這裏添加 HADOOP_CLIENT_OPTS

HADOOP_CLIENT_OPTS="$HADOOP_CLIENT_OPTS -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8765"

CLASS=org.apache.hadoop.util.RunJar

elif [ "$COMMAND" = "checknative" ] ; then

...

還不夠,需要區分JVM1 和JVM2的參數,hive提供了三個變量設置(看代碼糾出來的,官方文檔還沒介紹):

HIVE_DEBUG_RECURSIVE: 告訴hive要把 HADOOP_CLIENT_OPTS 變量傳給子JVM

HIVE_MAIN_CLIENT_DEBUG_OPTS和HIVE_CHILD_CLIENT_DEBUG_OPTS:hive在將HADOOP_CLIENT_OPTS傳給子JVM時,會把 HADOOP_CLIENT_OPTS中HIVE_MAIN_CLIENT_DEBUG_OPTS的值的部分,替換成HIVE_CHILD_CLIENT_DEBUG_OPTS的值(好繞啊)

所以最終的代碼應該是:

...

elif [ "$COMMAND" = "jar" ] ; then

if ! echo "$HADOOP_CLIENT_OPTS"|fgrep 'dt_socket' ; then

HADOOP_CLIENT_OPTS="$HADOOP_CLIENT_OPTS -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8765"

fi

HIVE_DEBUG_RECURSIVE=y

HIVE_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

CLASS=org.apache.hadoop.util.RunJar

elif [ "$COMMAND" = "checknative" ] ; then

...

還有壹種情況下hive做了優化,不需要提交MR任務,也就不用起第二個JVM:

SELECT * FROM ...

這時候attach到 8765端口就行,忽略HIVE_CHILD_CLIENT_DEBUG_OPTS

  • 上一篇:溫州編程哪裏學比較好
  • 下一篇:關於農業和反應物候知識的詩句
  • copyright 2024編程學習大全網