Hive中ORC數(shù)據(jù)文件參考

refer:https://www.cnblogs.com/ITtangtang/p/7677912.html

#ORC File文件結構

#ORC的全稱是(Optimized Row Columnar)劈狐,ORC文件格式是一種Hadoop生態(tài)圈中的列式存儲格式,它的產(chǎn)生早在2013年初呐馆,最初產(chǎn)生自Apache Hive肥缔,用于降低Hadoop數(shù)據(jù)存儲空間和加速Hive查詢速度。和Parquet類似汹来,它并不是一個單純的列式存儲格式续膳,仍然是首先根據(jù)行組分割整個表改艇,在每一個行組內(nèi)進行按列存儲。ORC文件是自描述的坟岔,它的元數(shù)據(jù)使用Protocol Buffers序列化谒兄,并且文件中的數(shù)據(jù)盡可能的壓縮以降低存儲空間的消耗,目前也被Spark SQL社付、Presto等查詢引擎支持承疲,但是Impala對于ORC目前沒有支持,仍然使用Parquet作為主要的列式存儲格式鸥咖。2015年ORC項目被Apache項目基金會提升為Apache頂級項目燕鸽。ORC具有以下一些優(yōu)勢:

#ORC是列式存儲,有多種文件壓縮方式啼辣,并且有著很高的壓縮比啊研。

#文件是可切分(Split)的。因此鸥拧,在Hive中使用ORC作為表的文件存儲格式党远,不僅節(jié)省HDFS存儲資源,查詢?nèi)蝿盏妮斎霐?shù)據(jù)量減少富弦,使用的MapTask也就減少了沟娱。

#提供了多種索引,row group index舆声、bloom filter index花沉。

#ORC可以支持復雜的數(shù)據(jù)結構(比如Map等)

#列式存儲  

  由于OLAP查詢的特點柳爽,列式存儲可以提升其查詢性能媳握,但是它是如何做到的呢?這就要從列式存儲的原理說起磷脯,從圖1中可以看到蛾找,相對于關系數(shù)據(jù)庫中通常使用的行式存儲,在使用列式存儲時每一列的所有元素都是順序存儲的赵誓。由此特點可以給查詢帶來如下的優(yōu)化:

1.查詢的時候不需要掃描全部的數(shù)據(jù)打毛,而只需要讀取每次查詢涉及的列,這樣可以將I/O消耗降低N倍俩功,另外可以保存每一列的統(tǒng)計信息(min幻枉、max、sum等)诡蜓,實現(xiàn)部分的謂詞下推熬甫。

2.由于每一列的成員都是同構的,可以針對不同的數(shù)據(jù)類型使用更高效的數(shù)據(jù)壓縮算法蔓罚,進一步減小I/O椿肩。

3.由于每一列的成員的同構性瞻颂,可以使用更加適合CPU pipeline的編碼方式,減小CPU的緩存失效郑象。

#關于Orc文件格式的官網(wǎng)介紹贡这,見:

https://cwiki.apache.org/confluence/display/Hive/LanguageManual+ORC

#需要注意的是,ORC在讀寫時候需要消耗額外的CPU資源來壓縮和解壓縮厂榛,當然這部分的CPU消耗是非常少的盖矫。


#數(shù)據(jù)模型

#和Parquet不同,ORC原生是不支持嵌套數(shù)據(jù)格式的击奶,而是通過對復雜數(shù)據(jù)類型特殊處理的方式實現(xiàn)嵌套格式的支持炼彪,例如對于如下的hive表:

CREATE TABLE `orcStructTable`(
? `name` string,
? `course` struct,
? `score` map,
? `work_locations` array)

在ORC的結構中包含了復雜類型列和原始類型,前者包括LIST正歼、STRUCT辐马、MAP和UNION類型,后者包括BOOLEAN局义、整數(shù)喜爷、浮點數(shù)、字符串類型等萄唇,其中STRUCT的孩子節(jié)點包括它的成員變量檩帐,可能有多個孩子節(jié)點,MAP有兩個孩子節(jié)點另萤,分別為key和value湃密,LIST包含一個孩子節(jié)點,類型為該LIST的成員類型四敞,UNION一般不怎么用得到泛源。每一個Schema樹的根節(jié)點為一個Struct類型,所有的column按照樹的中序遍歷順序編號忿危。

ORC只需要存儲schema樹中葉子節(jié)點的值达箍,而中間的非葉子節(jié)點只是做一層代理,它們只需要負責孩子節(jié)點值得讀取铺厨,只有真正的葉子節(jié)點才會讀取數(shù)據(jù)缎玫,然后交由父節(jié)點封裝成對應的數(shù)據(jù)結構返回。


#文件結構

#和Parquet類似解滓,ORC文件也是以二進制方式存儲的秒赤,所以是不可以直接讀取媳维,ORC文件也是自解析的,它包含許多的元數(shù)據(jù),這些元數(shù)據(jù)都是同構ProtoBuffer進行序列化的鞍泉。ORC的文件結構如下圖,其中涉及到如下的概念:

ORC文件:保存在文件系統(tǒng)上的普通二進制文件,一個ORC文件中可以包含多個stripe,每一個stripe包含多條記錄在扰,這些記錄按照列進行獨立存儲,對應到Parquet中的row group的概念雷客。

文件級元數(shù)據(jù):包括文件的描述信息PostScript芒珠、文件meta信息(包括整個文件的統(tǒng)計信息)、所有stripe的信息和文件schema信息搅裙。

1.stripe:一組行形成一個stripe皱卓,每次讀取文件是以行組為單位的,一般為HDFS的塊大小部逮,保存了每一列的索引和數(shù)據(jù)娜汁。

2.stripe元數(shù)據(jù):保存stripe的位置、每一個列的在該stripe的統(tǒng)計信息以及所有的stream類型和位置兄朋。

3.row group:索引的最小單位掐禁,一個stripe中包含多個row group,默認為10000個值組成颅和。

4.stream:一個stream表示文件中一段有效的數(shù)據(jù)傅事,包括索引和數(shù)據(jù)兩類。索引stream保存每一個row group的位置和統(tǒng)計信息峡扩,數(shù)據(jù)stream包括多種類型的數(shù)據(jù)蹭越,具體需要哪幾種是由該列類型和編碼方式?jīng)Q定。

  在ORC文件中保存了三個層級的統(tǒng)計信息教届,分別為文件級別响鹃、stripe級別和row group級別的,他們都可以用來根據(jù)Search ARGuments(謂詞下推條件)判斷是否可以跳過某些數(shù)據(jù)案训,在統(tǒng)計信息中都包含成員數(shù)和是否有null值买置,并且對于不同類型的數(shù)據(jù)設置一些特定的統(tǒng)計信息。

(1)file level

在ORC文件的末尾會記錄文件級別的統(tǒng)計信息萤衰,會記錄整個文件中columns的統(tǒng)計信息堕义。這些信息主要用于查詢的優(yōu)化,也可以為一些簡單的聚合查詢比如max, min, sum輸出結果脆栋。

(2)stripe level

ORC文件會保存每個字段stripe級別的統(tǒng)計信息,ORC reader使用這些統(tǒng)計信息來確定對于一個查詢語句來說洒擦,需要讀入哪些stripe中的記錄椿争。比如說某個stripe的字段max(a)=10,min(a)=3熟嫩,那么當where條件為a >10或者a <3時秦踪,那么這個stripe中的所有記錄在查詢語句執(zhí)行時不會被讀入。

(3)row level

為了進一步的避免讀入不必要的數(shù)據(jù),在邏輯上將一個column的index以一個給定的值(默認為10000椅邓,可由參數(shù)配置)分割為多個index組柠逞。以10000條記錄為一個組,對數(shù)據(jù)進行統(tǒng)計景馁。Hive查詢引擎會將where條件中的約束傳遞給ORC reader板壮,這些reader根據(jù)組級別的統(tǒng)計信息,過濾掉不必要的數(shù)據(jù)合住。如果該值設置的太小绰精,就會保存更多的統(tǒng)計信息,用戶需要根據(jù)自己數(shù)據(jù)的特點權衡一個合理的值


#ORC元數(shù)據(jù)

請參考:更高的壓縮比透葛,更好的性能–使用ORC文件格式優(yōu)化Hive

#數(shù)據(jù)訪問

讀取ORC文件是從尾部開始的笨使,第一次讀取16KB的大小,盡可能的將Postscript和Footer數(shù)據(jù)都讀入內(nèi)存僚害。文件的最后一個字節(jié)保存著PostScript的長度硫椰,它的長度不會超過256字節(jié),PostScript中保存著整個文件的元數(shù)據(jù)信息萨蚕,它包括文件的壓縮格式最爬、文件內(nèi)部每一個壓縮塊的最大長度(每次分配內(nèi)存的大小)、Footer長度门岔,以及一些版本信息爱致。在Postscript和Footer之間存儲著整個文件的統(tǒng)計信息(上圖中未畫出),這部分的統(tǒng)計信息包括每一個stripe中每一列的信息寒随,主要統(tǒng)計成員數(shù)糠悯、最大值、最小值妻往、是否有空值等互艾。

接下來讀取文件的Footer信息,它包含了每一個stripe的長度和偏移量讯泣,該文件的schema信息(將schema樹按照schema中的編號保存在數(shù)組中)纫普、整個文件的統(tǒng)計信息以及每一個row group的行數(shù)。

處理stripe時首先從Footer中獲取每一個stripe的其實位置和長度好渠、每一個stripe的Footer數(shù)據(jù)(元數(shù)據(jù)昨稼,記錄了index和data的的長度),整個striper被分為index和data兩部分拳锚,stripe內(nèi)部是按照row group進行分塊的(每一個row group中多少條記錄在文件的Footer中存儲)假栓,row group內(nèi)部按列存儲。每一個row group由多個stream保存數(shù)據(jù)和索引信息霍掺。每一個stream的數(shù)據(jù)會根據(jù)該列的類型使用特定的壓縮算法保存匾荆。在ORC中存在如下幾種stream類型:

PRESENT:每一個成員值在這個stream中保持一位(bit)用于標示該值是否為NULL拌蜘,通過它可以只記錄部位NULL的值

DATA:該列的中屬于當前stripe的成員值。

LENGTH:每一個成員的長度牙丽,這個是針對string類型的列才有的简卧。

DICTIONARY_DATA:對string類型數(shù)據(jù)編碼之后字典的內(nèi)容。

SECONDARY:存儲Decimal烤芦、timestamp類型的小數(shù)或者納秒數(shù)等举娩。

ROW_INDEX:保存stripe中每一個row group的統(tǒng)計信息和每一個row group起始位置信息。

  在初始化階段獲取全部的元數(shù)據(jù)之后拍棕,可以通過includes數(shù)組指定需要讀取的列編號晓铆,它是一個boolean數(shù)組,如果不指定則讀取全部的列绰播,還可以通過傳遞SearchArgument參數(shù)指定過濾條件骄噪,根據(jù)元數(shù)據(jù)首先讀取每一個stripe中的index信息,然后根據(jù)index中統(tǒng)計信息以及SearchArgument參數(shù)確定需要讀取的row group編號蠢箩,再根據(jù)includes數(shù)據(jù)決定需要從這些row group中讀取的列链蕊,通過這兩層的過濾需要讀取的數(shù)據(jù)只是整個stripe多個小段的區(qū)間,然后ORC會盡可能合并多個離散的區(qū)間盡可能的減少I/O次數(shù)谬泌。然后再根據(jù)index中保存的下一個row group的位置信息調至該stripe中第一個需要讀取的row group中滔韵。

  ORC文件格式只支持讀取指定字段,還不支持只讀取特殊字段類型中的指定部分掌实。?

  使用ORC文件格式時陪蜻,用戶可以使用HDFS的每一個block存儲ORC文件的一個stripe。對于一個ORC文件來說贱鼻,stripe的大小一般需要設置得比HDFS的block小宴卖,如果不這樣的話,一個stripe就會分別在HDFS的多個block上邻悬,當讀取這種數(shù)據(jù)時就會發(fā)生遠程讀數(shù)據(jù)的行為症昏。如果設置stripe的只保存在一個block上的話,如果當前block上的剩余空間不足以存儲下一個strpie父丰,ORC的writer接下來會將數(shù)據(jù)打散保存在block剩余的空間上肝谭,直到這個block存滿為止。這樣蛾扇,下一個stripe又會從下一個block開始存儲攘烛。

  由于ORC中使用了更加精確的索引信息,使得在讀取數(shù)據(jù)時可以指定從任意一行開始讀取屁桑,更細粒度的統(tǒng)計信息使得讀取ORC文件跳過整個row group医寿,ORC默認會對任何一塊數(shù)據(jù)和索引信息使用ZLIB壓縮,因此ORC文件占用的存儲空間也更小蘑斧,這點在后面的測試對比中也有所印證。


關于row group index和bloom filter index的性能優(yōu)化,請參考Hive性能優(yōu)化之ORC索引–Row Group Index vs Bloom Filter Index


#文件壓縮

ORC文件使用兩級壓縮機制竖瘾,首先將一個數(shù)據(jù)流使用流式編碼器進行編碼沟突,然后使用一個可選的壓縮器對數(shù)據(jù)流進行進一步壓縮。?

一個column可能保存在一個或多個數(shù)據(jù)流中捕传,可以將數(shù)據(jù)流劃分為以下四種類型:?

? Byte Stream

  字節(jié)流保存一系列的字節(jié)數(shù)據(jù)惠拭,不對數(shù)據(jù)進行編碼。?

? Run Length Byte Stream

  字節(jié)長度字節(jié)流保存一系列的字節(jié)數(shù)據(jù)庸论,對于相同的字節(jié)职辅,保存這個重復值以及該值在字節(jié)流中出現(xiàn)的位置。?

? Integer Stream

  整形數(shù)據(jù)流保存一系列整形數(shù)據(jù)聂示∮蛐可以對數(shù)據(jù)量進行字節(jié)長度編碼以及delta編碼。具體使用哪種編碼方式需要根據(jù)整形流中的子序列模式來確定鱼喉。?

? Bit Field Stream

  比特流主要用來保存boolean值組成的序列秀鞭,一個字節(jié)代表一個boolean值,在比特流的底層是用Run Length Byte Stream來實現(xiàn)的扛禽。?


#接下來會以Integer和String類型的字段舉例來說明锋边。?

(1)Integer

  對于一個整形字段,會同時使用一個比特流和整形流编曼。比特流用于標識某個值是否為null豆巨,整形流用于保存該整形字段非空記錄的整數(shù)值。?

(2)String

  對于一個String類型字段掐场,ORC writer在開始時會檢查該字段值中不同的內(nèi)容數(shù)占非空記錄總數(shù)的百分比不超過0.8的話往扔,就使用字典編碼,字段值會保存在一個比特流刻肄,一個字節(jié)流及兩個整形流中瓤球。比特流也是用于標識null值的,字節(jié)流用于存儲字典值敏弃,一個整形流用于存儲字典中每個詞條的長度卦羡,另一個整形流用于記錄字段值。?

  如果不能用字典編碼麦到,ORC writer會知道這個字段的重復值太少绿饵,用字典編碼效率不高,ORC writer會使用一個字節(jié)流保存String字段的值瓶颠,然后用一個整形流來保存每個字段的字節(jié)長度拟赊。?

  在ORC文件中,在各種數(shù)據(jù)流的底層粹淋,用戶可以自選ZLIB, Snappy和LZO壓縮方式對數(shù)據(jù)流進行壓縮吸祟。編碼器一般會將一個數(shù)據(jù)流壓縮成一個個小的壓縮單元瑟慈,在目前的實現(xiàn)中,壓縮單元的默認大小是256KB屋匕。


#參數(shù)可參看:

https://cwiki.apache.org/confluence/display/Hive/Configuration+Properties#ConfigurationProperties-ORCFileFormat

#

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末葛碧,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子过吻,更是在濱河造成了極大的恐慌进泼,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件纤虽,死亡現(xiàn)場離奇詭異乳绕,居然都是意外死亡,警方通過查閱死者的電腦和手機逼纸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進店門洋措,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人樊展,你說我怎么就攤上這事呻纹。” “怎么了专缠?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵雷酪,是天一觀的道長。 經(jīng)常有香客問我涝婉,道長哥力,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任墩弯,我火速辦了婚禮吩跋,結果婚禮上,老公的妹妹穿的比我還像新娘渔工。我一直安慰自己锌钮,他們只是感情好,可當我...
    茶點故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布引矩。 她就那樣靜靜地躺著梁丘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪旺韭。 梳的紋絲不亂的頭發(fā)上氛谜,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天,我揣著相機與錄音区端,去河邊找鬼值漫。 笑死,一個胖子當著我的面吹牛织盼,可吹牛的內(nèi)容都是我干的杨何。 我是一名探鬼主播酱塔,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼晚吞!你這毒婦竟也來了延旧?” 一聲冷哼從身側響起谋国,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤槽地,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后芦瘾,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體捌蚊,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年近弟,在試婚紗的時候發(fā)現(xiàn)自己被綠了缅糟。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,654評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡祷愉,死狀恐怖窗宦,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情二鳄,我是刑警寧澤赴涵,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站订讼,受9級特大地震影響髓窜,放射性物質發(fā)生泄漏。R本人自食惡果不足惜欺殿,卻給世界環(huán)境...
    茶點故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一寄纵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧脖苏,春花似錦程拭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蜒谤,卻和暖如春山宾,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背鳍徽。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工资锰, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人阶祭。 一個月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓绷杜,卻偏偏與公主長得像直秆,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子鞭盟,可洞房花燭夜當晚...
    茶點故事閱讀 43,543評論 2 349

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