快速理解Hive的數據存儲格式及mapreduce底層原理

在大數據工程師面試時,下面這個題可謂是面試官的最愛,他考察了對於mapreduce框架以及hive的原理的理解,閱讀完這篇文章,在面試這一類的問題時,就會胸有撐住了!

在創建hive表時,會有這樣一句:STORED AS TEXTFILE,這一句的作用,其實是

STORED AS INPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat'

OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat' 的簡寫。要想理解hive存儲格式或者Mapreduce的原理,我們先從理解InputFormat開始。

一、理解 InputFormat

InputFormat是個抽象類,他有兩個成員方法。理解了這兩個方法的作用,我們就知道InputFormat是用來做什麼的了。我們依次來看

1)第一個方法: List getSplits(JobContext var1),它實現了對文件切分成多個分片,分片對象的定義爲InputSplit,我們以他的一個實現:FileInputFormat 爲例,FileInputFormat繼承了InputFormat,實現了對於文件的讀入,下圖爲getSplits的實現。可以看到實現里根據computeSplitSize 方法取分塊大小,循環所有輸入文件,將拆分後的文件路徑,起始位置,長度,host等信息賦值到inputsplit對象上,這其實是一個邏輯上的劃分,數據在這一步不會發生任何變動。另外,在讀取文件時(截圖裏的listStatus方法內)還通過定義的PathFilter進行了文件過濾,去掉那些以.或_開頭的臨時文件等。

13553988-caa45687ab18ae7e

2)第二個方法:RecordReader<K,V> createRecordReader(InputSplit split, TaskAttemptContext context )

從函數定義來看,其實就是讀取InputSplit的分塊信息,返回了單獨的record。沒錯,這個函數的作用就是從InputSplit中正確讀出一條一條的key value值,供Mapper使用。

3)Hive定義中TextInputFormat的實現

我們再來看在定義hive表時,使用的TextInputFormat的實現,他是繼承了上面的FileInputFormat,重寫了 createRecordReader 方法使用LineRecordReader實現了文本讀取,重寫isSplitable增加了對於壓縮文件不可分割的判斷。

13553988-bf28f562cb4de55e

看到這裏,大家對於InputFormat的作用就比較清晰了,他提供了文件的過濾、切分以及每個split的明細讀取,爲下一步的map工作做好了前期準備。

二、Hive的存儲格式

那回到hive存儲格式的問題上,其實就是Hive對InputFormat 提供了不同的實現,用來解析爲優化hive速度而定義的不同存儲格式。hive主要有下面三種存儲格式。

1)textfile 也就是hive默認的存儲格式,數據可以使用任意分隔符進行分割,每一行爲一條記錄。默認無壓縮,可以用gzip、snappy等方式對數據壓縮,但是會造成無法對數據切分並行操作。(textInputFormat的isSplitable判斷)

2) sequencefile 這種方式是講hdfs上的數據進行二進制格式編碼,存儲進行了壓縮,有利於減少IO,也是基於行存儲。

3) rcfile:這種方式 是基於sequencefile存儲,但是是基於列存儲,列值通常重複值很多,所以更利於壓縮。這種方式壓縮率更高。他先對行進行分組 ,在對列進行合併。比如我們select 表中的一列數據時,只會對該列的數據進行處理,但是其他存儲方式不論select幾列會對所有數據都讀取出來。但是當select 全列時,rcfile反而不如sequencefile的性能高了。

13553988-da09951b8f9de52a

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章