Hive Format異常分析

最近在執(zhí)行Hive insert/select語句的過程碰到下面這種類型的異常:

# 異常1:
Caused by: java.lang.ClassCastException: org.apache.hadoop.io.Text cannot be cast to org.apache.hadoop.hive.ql.io.orc.OrcSerde$OrcSerdeRow
    at org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat$OrcRecordWriter.write(OrcOutputFormat.java:81)
    at org.apache.hadoop.hive.ql.exec.FileSinkOperator.process(FileSinkOperator.java:753)
    at org.apache.hadoop.hive.ql.exec.Operator.forward(Operator.java:837)
    at org.apache.hadoop.hive.ql.exec.LimitOperator.process(LimitOperator.java:54)
    at org.apache.hadoop.hive.ql.exec.Operator.forward(Operator.java:837)
    at org.apache.hadoop.hive.ql.exec.SelectOperator.process(SelectOperator.java:88)
    at org.apache.hadoop.hive.ql.exec.mr.ExecReducer.reduce(ExecReducer.java:235)
    ... 7 more
# 異常2:
Failed with exception java.io.IOException:java.lang.ClassCastException: org.apache.hadoop.hive.ql.io.orc.OrcStruct cannot be cast to org.apache.hadoop.io.BinaryComparable

本文已上述的錯誤為切入點(diǎn)孝宗,分析下異常原因以及Hive相關(guān)的關(guān)于Format的異常。主要內(nèi)容如下:

1. 異常的原因分析及解決方法
2. FAQ

1. 異常的原因分析及解決方法

1.1 異常1分析

# 異常1:
Caused by: java.lang.ClassCastException: org.apache.hadoop.io.Text cannot be cast to org.apache.hadoop.hive.ql.io.orc.OrcSerde$OrcSerdeRow
    at org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat$OrcRecordWriter.write(OrcOutputFormat.java:81)
    at org.apache.hadoop.hive.ql.exec.FileSinkOperator.process(FileSinkOperator.java:753)
    at org.apache.hadoop.hive.ql.exec.Operator.forward(Operator.java:837)
    at org.apache.hadoop.hive.ql.exec.LimitOperator.process(LimitOperator.java:54)
    at org.apache.hadoop.hive.ql.exec.Operator.forward(Operator.java:837)
    at org.apache.hadoop.hive.ql.exec.SelectOperator.process(SelectOperator.java:88)
    at org.apache.hadoop.hive.ql.exec.mr.ExecReducer.reduce(ExecReducer.java:235)
    ... 7 more

該異常發(fā)生在insert overwrite階段忍抽,即select出來的數(shù)據(jù)插入目標(biāo)表時拋出異常。從異常棧中可以清楚地看到OrcOutputFormat董朝、java.lang.ClassCastException這些信息鸠项,可見這是Reduce任務(wù)將最終結(jié)果進(jìn)行持久化(寫入HDFS文件系統(tǒng))時出現(xiàn)錯誤。首先子姜,我們需要明確這個數(shù)據(jù)持久化的大體流程是什么樣的祟绊?如下圖所示:

read-process

Read過程:InputFormat將輸入流(InputStream)分割成紀(jì)錄(<key,value>)哥捕,Deserializer將紀(jì)錄(<key牧抽,value>)解析成列對象。

write-process

Write過程:Serializer將列對象轉(zhuǎn)化為紀(jì)錄(<key遥赚,value>)扬舒,OutputFormat將紀(jì)錄(<key,value>)格式化為輸出流(OutputStream)凫佛。

上圖中描繪的分別是數(shù)據(jù)載入內(nèi)存和持久化的過程讲坎。異常信息中的OrcOutputFormat說明錯誤出在數(shù)據(jù)持久化過程中。從圖中可知愧薛,序列化器Serializer的輸出數(shù)據(jù)晨炕,就是OutputFormat的輸入數(shù)據(jù)。接下來就是確定目標(biāo)表的SerDe/InputFormat/OutputFormat分別是什么毫炉。通過下面命令查看瓮栗。

desc formatted $table

結(jié)果如下:

# desc formatted $table
# Storage Information
SerDe Library:          org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe
InputFormat:            org.apache.hadoop.hive.ql.io.orc.OrcInputFormat
OutputFormat:           org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat

由上可知,目標(biāo)表的SerDe為LazySimpleSerDe碘箍,而其Input/OutputFormat是orc的遵馆。所以異常1的原因也就得出:

異常1原因:序列化/反序列化器LazySimpleSerDe在執(zhí)行serialize后的結(jié)果類型是Text,而OrcOutputFormat的接收數(shù)據(jù)類型必須是OrcSerdeRow丰榴。這就造成了ClassCastException。

下面是OrcOutputFormat的write方法源碼:

public class OrcOutputFormat extends ... {
    
    @Override
    public void write(Writable row) throws IOException {
      // 若類型不匹配秆撮,會拋出異常四濒。
      OrcSerdeRow serdeRow = (OrcSerdeRow) row;
      if (writer == null) {
        options.inspector(serdeRow.getInspector());
        writer = OrcFile.createWriter(path, options);
      }
      writer.addRow(serdeRow.getRow());
    }
    。。盗蟆。
}

原因找到后戈二,解決辦法就很簡單了,將該table的fileformat修改為orc即可喳资,如下所示:

ALTER TABLE $table SET FILEFORMAT ORC;

1.2 異常2分析

# 異常2:
Failed with exception java.io.IOException:java.lang.ClassCastException: org.apache.hadoop.hive.ql.io.orc.OrcStruct cannot be cast to org.apache.hadoop.io.BinaryComparable

通過異常1的分析后觉吭,這個異常的原因也就很容易定位了,數(shù)據(jù)讀取階段:OrcInputFormat的輸出結(jié)果是OrcStruct類型仆邓,其作為輸入數(shù)據(jù)傳給LazySimpleSerDe的deserialize方法鲜滩,很明顯,deserialize中進(jìn)行類型轉(zhuǎn)換時拋出該異常节值。下面是LazySimpleSerDe的doDeserialize方法源碼:

  @Override
  public Object doDeserialize(Writable field) throws SerDeException {
    if (byteArrayRef == null) {
      byteArrayRef = new ByteArrayRef();
    }
    // OrcStruct -> BinaryComparable
    BinaryComparable b = (BinaryComparable) field;
    byteArrayRef.setData(b.getBytes());
    cachedLazyStruct.init(byteArrayRef, 0, b.getLength());
    lastOperationSerialize = false;
    lastOperationDeserialize = true;
    return cachedLazyStruct;
  }

下圖是已TEXTFILE格式作為存儲格式時的讀取流程:


textfile-read-process

現(xiàn)在將TextInputFormat換成OrcInputFormat后:


orc-text-incompatible

小結(jié):以上兩種異常的根本原因都是由于序列化/反序列化器SerDe和InputFormat/OutputFormat不匹配造成的徙硅。這通常是由于創(chuàng)建表時沒有正確指定這三個配置項(xiàng)造成的。

FAQ

1. stored as orc 和 stored as INPUTFORMAT ... OUTPUTFORMAT ...的區(qū)別搞疗?

當(dāng)我們使用stored as orc的時候嗓蘑,其實(shí)已經(jīng)隱式的指定了下面三個配置:

  1. SERDE:org.apache.hadoop.hive.ql.io.orc.OrcSerde
  2. INPUTFORMAT:org.apache.hadoop.hive.ql.io.orc.OrcInputFormat
  3. OUTPUTFORMAT:org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat

當(dāng)我們顯示的指定STORED AS INPUTFORMAT/OUTPUTFORMAT:

STORED AS INPUTFORMAT
  ‘org.apache.hadoop.hive.ql.io.orc.OrcInputFormat’
OUTPUTFORMAT
  ‘org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat’

此時SERDE并沒有指定,會使用默認(rèn)的serde匿乃,在hive cli中可以通過下面cmd查看:

set hive.default.serde;
hive.default.serde=org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe

當(dāng)然了桩皿,如果hive-site.xml中已經(jīng)配置了hive.default.fileformat,那么不知道stored as的情況下幢炸,會使用hive.default.fileformat指定的文件格式泄隔。

<property>
        <name>hive.default.fileformat</name>
        <value>ORC</value>
</property>

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市阳懂,隨后出現(xiàn)的幾起案子梅尤,更是在濱河造成了極大的恐慌,老刑警劉巖岩调,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件巷燥,死亡現(xiàn)場離奇詭異,居然都是意外死亡号枕,警方通過查閱死者的電腦和手機(jī)缰揪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來葱淳,“玉大人钝腺,你說我怎么就攤上這事≡薏蓿” “怎么了艳狐?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長皿桑。 經(jīng)常有香客問我毫目,道長蔬啡,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任镀虐,我火速辦了婚禮箱蟆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘刮便。我一直安慰自己空猜,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布恨旱。 她就那樣靜靜地躺著辈毯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪窖杀。 梳的紋絲不亂的頭發(fā)上漓摩,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天,我揣著相機(jī)與錄音入客,去河邊找鬼管毙。 笑死,一個胖子當(dāng)著我的面吹牛桌硫,可吹牛的內(nèi)容都是我干的夭咬。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼铆隘,長吁一口氣:“原來是場噩夢啊……” “哼哨苛!你這毒婦竟也來了慷荔?” 一聲冷哼從身側(cè)響起洲脂,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤竹勉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后肿嘲,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體融击,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年雳窟,在試婚紗的時候發(fā)現(xiàn)自己被綠了尊浪。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡封救,死狀恐怖拇涤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情誉结,我是刑警寧澤鹅士,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站惩坑,受9級特大地震影響如绸,放射性物質(zhì)發(fā)生泄漏嘱朽。R本人自食惡果不足惜旭贬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一怔接、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧稀轨,春花似錦扼脐、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至佣谐,卻和暖如春肚吏,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背狭魂。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工罚攀, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人雌澄。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓斋泄,卻偏偏與公主長得像,于是被迫代替她去往敵國和親镐牺。 傳聞我的和親對象是個殘疾皇子炫掐,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內(nèi)容