大數據:Hive - ORC 文件存儲(chu)格(ge)式
一、ORC File文(wen)件結構
ORC的全稱是(shi)(Optimized Row Columnar),ORC文件(jian)格式(shi)是(shi)一種(zhong)Hadoop生(sheng)態(tai)圈中的列(lie)(lie)(lie)式(shi)存(cun)(cun)儲格式(shi),它的產(chan)生(sheng)早在2013年(nian)(nian)初,最初產(chan)生(sheng)自Apache Hive,用(yong)于(yu)降低Hadoop數(shu)據(ju)存(cun)(cun)儲空(kong)間和(he)(he)加速Hive查詢(xun)速度。和(he)(he)Parquet類似(si),它并不是(shi)一個(ge)(ge)單純(chun)的列(lie)(lie)(lie)式(shi)存(cun)(cun)儲格式(shi),仍然是(shi)首先(xian)根(gen)據(ju)行(xing)組分割(ge)整個(ge)(ge)表,在每(mei)一個(ge)(ge)行(xing)組內進行(xing)按列(lie)(lie)(lie)存(cun)(cun)儲。ORC文件(jian)是(shi)自描述的,它的元數(shu)據(ju)使用(yong)Protocol Buffers序(xu)列(lie)(lie)(lie)化,并且文件(jian)中的數(shu)據(ju)盡可能(neng)的壓縮(suo)以降低存(cun)(cun)儲空(kong)間的消耗(hao),目前(qian)也被(bei)Spark SQL、Presto等查詢(xun)引擎支持,但是(shi)Impala對于(yu)ORC目前(qian)沒有(you)支持,仍然使用(yong)Parquet作為(wei)主要的列(lie)(lie)(lie)式(shi)存(cun)(cun)儲格式(shi)。2015年(nian)(nian)ORC項(xiang)目被(bei)Apache項(xiang)目基金(jin)會提(ti)升(sheng)為(wei)Apache頂級項(xiang)目。ORC具有(you)以下一些優勢:
- ORC是列式存儲,有多種文(wen)件壓縮方式,并(bing)且有著很高(gao)的壓縮比。
- 文(wen)(wen)件(jian)是可切分(fen)(Split)的。因此(ci),在Hive中使(shi)用(yong)ORC作為表(biao)的文(wen)(wen)件(jian)存(cun)儲(chu)格式,不僅節(jie)省(sheng)HDFS存(cun)儲(chu)資源,查詢任務的輸入數(shu)據量減少(shao),使(shi)用(yong)的MapTask也就減少(shao)了(le)。
- 提供了多種索引,row group index、bloom filter index。
- ORC可(ke)以支持復雜的數據結(jie)構(gou)(比如Map等)
列式存(cun)儲
由(you)于OLAP查(cha)(cha)詢的(de)特點,列式(shi)存儲(chu)可(ke)以提(ti)升其查(cha)(cha)詢性能,但(dan)是(shi)它是(shi)如(ru)(ru)何(he)做到的(de)呢?這(zhe)就要從列式(shi)存儲(chu)的(de)原(yuan)理(li)說起,從圖1中可(ke)以看(kan)到,相(xiang)對于關系(xi)數據庫(ku)中通(tong)常使(shi)用的(de)行式(shi)存儲(chu),在使(shi)用列式(shi)存儲(chu)時每(mei)一列的(de)所有元素都是(shi)順序存儲(chu)的(de)。由(you)此特點可(ke)以給查(cha)(cha)詢帶來如(ru)(ru)下的(de)優化:
- 查詢(xun)的時候(hou)不(bu)需(xu)要掃描全部的數據,而只需(xu)要讀(du)取(qu)每次查詢(xun)涉及(ji)的列(lie),這(zhe)樣可(ke)以將(jiang)I/O消(xiao)耗降低N倍,另外可(ke)以保存每一列(lie)的統計(ji)信息(xi)(min、max、sum等),實現部分的謂詞下推。
- 由于每一(yi)列(lie)的成(cheng)員(yuan)都是同構的,可以針對(dui)不同的數(shu)據(ju)類(lei)型使(shi)用更高效的數(shu)據(ju)壓縮算法,進一(yi)步減小I/O。
- 由于每一列(lie)的成員(yuan)的同構性,可以使(shi)用更加適合(he)CPU pipeline的編碼方式(shi),減小CPU的緩存失效。

關(guan)于Orc文件格(ge)式的官網介紹,見(jian):
需要(yao)注意的(de)是,ORC在(zai)讀(du)寫時候需要(yao)消(xiao)耗額外的(de)CPU資源來壓(ya)縮和解壓(ya)縮,當然這(zhe)部分(fen)的(de)CPU消(xiao)耗是非常(chang)少的(de)。
數據模(mo)型(xing)
和Parquet不同,ORC原生是不支(zhi)持嵌套數據(ju)(ju)格式(shi)的(de)(de),而(er)是通過對復雜數據(ju)(ju)類型特殊(shu)處理(li)的(de)(de)方式(shi)實現嵌套格式(shi)的(de)(de)支(zhi)持,例(li)如(ru)對于如(ru)下(xia)的(de)(de)hive表:
CREATE TABLE `orcStructTable`(
`name` string,
`course` struct<course:string,score:int>,
`score` map<string,int>,
`work_locations` array<string>
)
在ORC的(de)(de)結構中包(bao)含(han)了復雜類(lei)型列和(he)原始類(lei)型,前者(zhe)包(bao)括LIST、STRUCT、MAP和(he)UNION類(lei)型,后者(zhe)包(bao)括BOOLEAN、整數、浮點(dian)(dian)數、字符串(chuan)類(lei)型等,其中STRUCT的(de)(de)孩子節(jie)點(dian)(dian)包(bao)括它的(de)(de)成(cheng)員變量,可能有多個孩子節(jie)點(dian)(dian),MAP有兩個孩子節(jie)點(dian)(dian),分別(bie)為key和(he)value,LIST包(bao)含(han)一(yi)個孩子節(jie)點(dian)(dian),類(lei)型為該(gai)LIST的(de)(de)成(cheng)員類(lei)型,UNION一(yi)般不怎么用得(de)到(dao)。每(mei)一(yi)個Schema樹的(de)(de)根(gen)節(jie)點(dian)(dian)為一(yi)個Struct類(lei)型,所有的(de)(de)column按照樹的(de)(de)中序遍歷順序編號。
ORC只需要存儲schema樹中葉子節點的值,而中間的非葉子節點只是做一層代理,它們只需要負責孩子節點值得讀取,只有真正的葉子節點才會讀取數據,然后交由父節點封裝成對應的數據結構返回。
文件結構(gou)
和Parquet類似,ORC文(wen)件(jian)(jian)也是(shi)以(yi)二進制方式存(cun)儲的,所(suo)以(yi)是(shi)不可以(yi)直接讀取,ORC文(wen)件(jian)(jian)也是(shi)自(zi)解析的,它包含許多的元(yuan)數據,這些元(yuan)數據都是(shi)同構ProtoBuffer進行序列(lie)化的。ORC的文(wen)件(jian)(jian)結構如下(xia)圖,其中涉及到(dao)如下(xia)的概念:
- ORC文(wen)(wen)件:保(bao)存在文(wen)(wen)件系統上的(de)普通二進制文(wen)(wen)件,一個(ge)(ge)ORC文(wen)(wen)件中可(ke)以包含(han)多(duo)個(ge)(ge)stripe,每一個(ge)(ge)stripe包含(han)多(duo)條(tiao)記錄,這(zhe)些記錄按照列進行獨立存儲,對應(ying)到Parquet中的(de)row group的(de)概念。
- 文(wen)(wen)件(jian)級元數(shu)據(ju):包括文(wen)(wen)件(jian)的描述(shu)信息(xi)(xi)PostScript、文(wen)(wen)件(jian)meta信息(xi)(xi)(包括整(zheng)個(ge)文(wen)(wen)件(jian)的統計(ji)信息(xi)(xi))、所有stripe的信息(xi)(xi)和文(wen)(wen)件(jian)schema信息(xi)(xi)。
- stripe:一(yi)(yi)組行(xing)形成一(yi)(yi)個stripe,每(mei)次讀取文件是以行(xing)組為(wei)單(dan)位(wei)的(de),一(yi)(yi)般為(wei)HDFS的(de)塊大小,保存了每(mei)一(yi)(yi)列的(de)索引和數據。
- stripe元(yuan)數據:保存(cun)stripe的位置、每(mei)一個列的在該stripe的統計信息(xi)以及所有的stream類型和(he)位置。
- row group:索引(yin)的(de)最小單位(wei),一(yi)個stripe中包(bao)含多(duo)個row group,默認為(wei)10000個值組(zu)成。
- stream:一(yi)個stream表示文件中一(yi)段有效(xiao)的數(shu)(shu)據,包(bao)括索(suo)引和(he)數(shu)(shu)據兩類(lei)。索(suo)引stream保(bao)存每一(yi)個row group的位置和(he)統計信息,數(shu)(shu)據stream包(bao)括多種類(lei)型的數(shu)(shu)據,具體需(xu)要(yao)哪幾種是由該列類(lei)型和(he)編(bian)碼(ma)方式決(jue)定。

在ORC文件(jian)中保存了(le)三個層級(ji)(ji)(ji)的(de)(de)統計(ji)信(xin)(xin)息(xi),分(fen)別為文件(jian)級(ji)(ji)(ji)別、stripe級(ji)(ji)(ji)別和row group級(ji)(ji)(ji)別的(de)(de),他們都可以用(yong)來根據Search ARGuments(謂詞下推條(tiao)件(jian))判斷是否可以跳過(guo)某(mou)些(xie)數(shu)據,在統計(ji)信(xin)(xin)息(xi)中都包含成員數(shu)和是否有null值,并且(qie)對于(yu)不同(tong)類(lei)型的(de)(de)數(shu)據設置一些(xie)特(te)定的(de)(de)統計(ji)信(xin)(xin)息(xi)。
(1)file level
在ORC文件的末尾會記錄文件級別的統計信息,會記錄整個文件中columns的統計信息。這些信息主要用于查詢的優化,也可以為一些簡單的聚合查詢比如max, min, sum輸出結果。
(2)stripe level
ORC文件會保存每個字段stripe級別的統計信息,ORC reader使用這些統計信息來確定對于一個查詢語句來說,需要讀入哪些stripe中的記錄。比如說某個stripe的字段max(a)=10,min(a)=3,那么當where條件為a >10或者a <3時,那么這個stripe中的所有記錄在查詢語句執行時不會被讀入。
(3)row level
為了進一步的避免讀入不必要的數據,在邏輯上將一個column的index以一個給定的值(默認為10000,可由參數配置)分割為多個index組。以10000條記錄為一個組,對數據進行統計。Hive查詢引擎會將where條件中的約束傳遞給ORC reader,這些reader根據組級別的統計信息,過濾掉不必要的數據。如果該值設置的太小,就會保存更多的統計信息,用戶需要根據自己數據的特點權衡一個合理的值
ORC元數據
請(qing)參考:
數據訪問(wen)
讀(du)(du)取(qu)ORC文(wen)件(jian)是(shi)從尾部(bu)開始的(de)(de)(de),第一(yi)(yi)次讀(du)(du)取(qu)16KB的(de)(de)(de)大(da)小,盡可(ke)能的(de)(de)(de)將Postscript和Footer數據都讀(du)(du)入(ru)內(nei)存。文(wen)件(jian)的(de)(de)(de)最后一(yi)(yi)個(ge)(ge)字節保存著PostScript的(de)(de)(de)長度(du)(du),它(ta)的(de)(de)(de)長度(du)(du)不會超過(guo)256字節,PostScript中保存著整(zheng)個(ge)(ge)文(wen)件(jian)的(de)(de)(de)元數據信息(xi)(xi),它(ta)包括(kuo)文(wen)件(jian)的(de)(de)(de)壓(ya)(ya)縮格式、文(wen)件(jian)內(nei)部(bu)每一(yi)(yi)個(ge)(ge)壓(ya)(ya)縮塊的(de)(de)(de)最大(da)長度(du)(du)(每次分配(pei)內(nei)存的(de)(de)(de)大(da)小)、Footer長度(du)(du),以及一(yi)(yi)些版本信息(xi)(xi)。在Postscript和Footer之間(jian)存儲著整(zheng)個(ge)(ge)文(wen)件(jian)的(de)(de)(de)統(tong)計信息(xi)(xi)(上圖中未畫出),這部(bu)分的(de)(de)(de)統(tong)計信息(xi)(xi)包括(kuo)每一(yi)(yi)個(ge)(ge)stripe中每一(yi)(yi)列的(de)(de)(de)信息(xi)(xi),主要統(tong)計成員數、最大(da)值(zhi)、最小值(zhi)、是(shi)否(fou)有(you)空值(zhi)等。
接下(xia)來(lai)讀取文(wen)(wen)件的(de)Footer信息,它包含了(le)每一(yi)(yi)個stripe的(de)長度和偏移量,該文(wen)(wen)件的(de)schema信息(將schema樹按(an)照schema中(zhong)的(de)編號保存在數(shu)組中(zhong))、整個文(wen)(wen)件的(de)統計信息以及每一(yi)(yi)個row group的(de)行(xing)數(shu)。
處理stripe時(shi)首先從Footer中(zhong)獲取每一(yi)(yi)個stripe的(de)(de)(de)其(qi)實位置(zhi)和(he)長度、每一(yi)(yi)個stripe的(de)(de)(de)Footer數據(ju)(ju)(元數據(ju)(ju),記(ji)錄(lu)了index和(he)data的(de)(de)(de)的(de)(de)(de)長度),整個striper被分(fen)為index和(he)data兩部分(fen),stripe內(nei)部是按(an)照row group進(jin)行分(fen)塊的(de)(de)(de)(每一(yi)(yi)個row group中(zhong)多少條記(ji)錄(lu)在(zai)文件的(de)(de)(de)Footer中(zhong)存(cun)儲(chu)(chu)),row group內(nei)部按(an)列(lie)存(cun)儲(chu)(chu)。每一(yi)(yi)個row group由多個stream保(bao)存(cun)數據(ju)(ju)和(he)索(suo)引信息。每一(yi)(yi)個stream的(de)(de)(de)數據(ju)(ju)會根據(ju)(ju)該列(lie)的(de)(de)(de)類(lei)(lei)型使用(yong)特定的(de)(de)(de)壓縮算法(fa)保(bao)存(cun)。在(zai)ORC中(zhong)存(cun)在(zai)如(ru)下幾種stream類(lei)(lei)型:
- PRESENT:每一個成員值在這個stream中保持一位(bit)用于標示該值是否為NULL,通過它可以只記錄部位NULL的值
- DATA:該列的中屬于當前stripe的成員值。
- LENGTH:每一個成員的長度,這個是針對string類型的列才有的。
- DICTIONARY_DATA:對string類型數據編碼之后字典的內容。
- SECONDARY:存儲Decimal、timestamp類型的小數或者納秒數等。
- ROW_INDEX:保存stripe中每一個row group的統計信息和每一個row group起始位置信息。
在初始化階(jie)段獲取全(quan)部(bu)的(de)(de)(de)元數(shu)據(ju)(ju)(ju)之(zhi)后(hou),可以(yi)通(tong)過(guo)(guo)includes數(shu)組(zu)(zu)指定(ding)(ding)需(xu)要(yao)讀(du)(du)取的(de)(de)(de)列(lie)編(bian)號,它是(shi)一個(ge)(ge)boolean數(shu)組(zu)(zu),如果不指定(ding)(ding)則讀(du)(du)取全(quan)部(bu)的(de)(de)(de)列(lie),還可以(yi)通(tong)過(guo)(guo)傳遞SearchArgument參數(shu)指定(ding)(ding)過(guo)(guo)濾(lv)條件,根(gen)(gen)據(ju)(ju)(ju)元數(shu)據(ju)(ju)(ju)首先讀(du)(du)取每一個(ge)(ge)stripe中(zhong)(zhong)(zhong)的(de)(de)(de)index信(xin)息(xi),然(ran)后(hou)根(gen)(gen)據(ju)(ju)(ju)index中(zhong)(zhong)(zhong)統計信(xin)息(xi)以(yi)及(ji)SearchArgument參數(shu)確定(ding)(ding)需(xu)要(yao)讀(du)(du)取的(de)(de)(de)row group編(bian)號,再根(gen)(gen)據(ju)(ju)(ju)includes數(shu)據(ju)(ju)(ju)決定(ding)(ding)需(xu)要(yao)從這些row group中(zhong)(zhong)(zhong)讀(du)(du)取的(de)(de)(de)列(lie),通(tong)過(guo)(guo)這兩層的(de)(de)(de)過(guo)(guo)濾(lv)需(xu)要(yao)讀(du)(du)取的(de)(de)(de)數(shu)據(ju)(ju)(ju)只是(shi)整(zheng)個(ge)(ge)stripe多個(ge)(ge)小段的(de)(de)(de)區(qu)間,然(ran)后(hou)ORC會(hui)盡可能合并多個(ge)(ge)離散的(de)(de)(de)區(qu)間盡可能的(de)(de)(de)減少(shao)I/O次數(shu)。然(ran)后(hou)再根(gen)(gen)據(ju)(ju)(ju)index中(zhong)(zhong)(zhong)保(bao)存的(de)(de)(de)下一個(ge)(ge)row group的(de)(de)(de)位置信(xin)息(xi)調(diao)至該stripe中(zhong)(zhong)(zhong)第一個(ge)(ge)需(xu)要(yao)讀(du)(du)取的(de)(de)(de)row group中(zhong)(zhong)(zhong)。
ORC文件格式只支(zhi)持(chi)讀(du)(du)取指(zhi)定字(zi)段,還不支(zhi)持(chi)只讀(du)(du)取特殊字(zi)段類型中的指(zhi)定部(bu)分。
使用(yong)(yong)(yong)ORC文(wen)件(jian)格式(shi)時,用(yong)(yong)(yong)戶可(ke)以使用(yong)(yong)(yong)HDFS的(de)(de)(de)每一(yi)個(ge)(ge)block存(cun)(cun)儲(chu)ORC文(wen)件(jian)的(de)(de)(de)一(yi)個(ge)(ge)stripe。對于一(yi)個(ge)(ge)ORC文(wen)件(jian)來說,stripe的(de)(de)(de)大小一(yi)般需要設(she)置得(de)比HDFS的(de)(de)(de)block小,如果(guo)不這樣的(de)(de)(de)話(hua),一(yi)個(ge)(ge)stripe就會分別在HDFS的(de)(de)(de)多(duo)個(ge)(ge)block上(shang)(shang),當(dang)讀(du)取這種數據時就會發(fa)生遠程讀(du)數據的(de)(de)(de)行為(wei)。如果(guo)設(she)置stripe的(de)(de)(de)只保(bao)存(cun)(cun)在一(yi)個(ge)(ge)block上(shang)(shang)的(de)(de)(de)話(hua),如果(guo)當(dang)前(qian)block上(shang)(shang)的(de)(de)(de)剩(sheng)余(yu)空間不足以存(cun)(cun)儲(chu)下一(yi)個(ge)(ge)strpie,ORC的(de)(de)(de)writer接下來會將數據打散保(bao)存(cun)(cun)在block剩(sheng)余(yu)的(de)(de)(de)空間上(shang)(shang),直(zhi)到這個(ge)(ge)block存(cun)(cun)滿為(wei)止。這樣,下一(yi)個(ge)(ge)stripe又會從下一(yi)個(ge)(ge)block開始(shi)存(cun)(cun)儲(chu)。
由于ORC中(zhong)使用(yong)了更(geng)加(jia)精(jing)確(que)的(de)索(suo)引信(xin)息,使得(de)在(zai)(zai)讀取數據時可以指定從任(ren)意一行開始讀取,更(geng)細粒度的(de)統(tong)計信(xin)息使得(de)讀取ORC文件跳過整(zheng)個row group,ORC默(mo)認會對(dui)任(ren)何一塊(kuai)數據和索(suo)引信(xin)息使用(yong)ZLIB壓縮,因此ORC文件占用(yong)的(de)存儲(chu)空間也更(geng)小,這點在(zai)(zai)后面的(de)測試對(dui)比中(zhong)也有所印(yin)證。
關于row group index和bloom filter index的性能優化,請參考
文件(jian)壓(ya)縮
ORC文(wen)件使(shi)用兩級壓(ya)縮機制(zhi),首先將一個數據(ju)流(liu)使(shi)用流(liu)式編碼器進行(xing)(xing)編碼,然(ran)后使(shi)用一個可選(xuan)的壓(ya)縮器對數據(ju)流(liu)進行(xing)(xing)進一步壓(ya)縮。
一個column可能保存在一個或多個數據流中,可以將數據流劃(hua)分為以下四種(zhong)類型:
? Byte Stream
字(zi)節流保存一系列的字(zi)節數(shu)(shu)據,不(bu)對數(shu)(shu)據進行編碼。
? Run Length Byte Stream
字(zi)節長度字(zi)節流保(bao)存一系列的字(zi)節數(shu)據,對于相同的字(zi)節,保(bao)存這個(ge)重復值(zhi)(zhi)以(yi)及該值(zhi)(zhi)在字(zi)節流中出現的位置。
? Integer Stream
整形(xing)數(shu)(shu)(shu)據(ju)流保(bao)存(cun)一系列(lie)整形(xing)數(shu)(shu)(shu)據(ju)。可以對數(shu)(shu)(shu)據(ju)量進行字節長度編(bian)碼以及(ji)delta編(bian)碼。具體使(shi)用哪種(zhong)編(bian)碼方(fang)式(shi)需要根據(ju)整形(xing)流中的(de)子序列(lie)模式(shi)來確定。
? Bit Field Stream
比(bi)特(te)流(liu)主要用來保(bao)存boolean值組成的(de)(de)序(xu)列,一(yi)個(ge)字節(jie)代表一(yi)個(ge)boolean值,在比(bi)特(te)流(liu)的(de)(de)底(di)層是用Run Length Byte Stream來實現的(de)(de)。
接下來會以Integer和String類型的字段(duan)舉例來說明(ming)。
(1)Integer
對于一(yi)個(ge)整(zheng)(zheng)形字段,會同時使用一(yi)個(ge)比特流和(he)整(zheng)(zheng)形流。比特流用于標識某(mou)個(ge)值是否為null,整(zheng)(zheng)形流用于保存該整(zheng)(zheng)形字段非空(kong)記錄的整(zheng)(zheng)數值。
(2)String
對于(yu)一(yi)(yi)個String類型字(zi)段(duan)(duan),ORC writer在開始時會(hui)檢查該字(zi)段(duan)(duan)值(zhi)(zhi)(zhi)中(zhong)(zhong)不同的(de)(de)內容數占非空(kong)記(ji)錄總數的(de)(de)百分比不超過0.8的(de)(de)話,就使(shi)用(yong)字(zi)典編碼,字(zi)段(duan)(duan)值(zhi)(zhi)(zhi)會(hui)保存在一(yi)(yi)個比特(te)流(liu),一(yi)(yi)個字(zi)節(jie)流(liu)及兩個整形流(liu)中(zhong)(zhong)。比特(te)流(liu)也是用(yong)于(yu)標識null值(zhi)(zhi)(zhi)的(de)(de),字(zi)節(jie)流(liu)用(yong)于(yu)存儲字(zi)典值(zhi)(zhi)(zhi),一(yi)(yi)個整形流(liu)用(yong)于(yu)存儲字(zi)典中(zhong)(zhong)每個詞條的(de)(de)長(chang)度,另一(yi)(yi)個整形流(liu)用(yong)于(yu)記(ji)錄字(zi)段(duan)(duan)值(zhi)(zhi)(zhi)。
如(ru)果不能用(yong)字典編碼(ma),ORC writer會知(zhi)道這個(ge)字段(duan)的(de)重復(fu)值太(tai)少,用(yong)字典編碼(ma)效率不高(gao),ORC writer會使(shi)用(yong)一個(ge)字節流保(bao)存String字段(duan)的(de)值,然(ran)后用(yong)一個(ge)整形流來保(bao)存每個(ge)字段(duan)的(de)字節長(chang)度(du)。
在(zai)ORC文件中(zhong),在(zai)各(ge)種數據(ju)流的(de)底(di)層,用戶可以(yi)自(zi)選(xuan)ZLIB, Snappy和(he)LZO壓(ya)縮(suo)方式對(dui)數據(ju)流進行壓(ya)縮(suo)。編(bian)碼器一(yi)般會(hui)將一(yi)個數據(ju)流壓(ya)縮(suo)成一(yi)個個小(xiao)的(de)壓(ya)縮(suo)單元,在(zai)目前的(de)實現(xian)中(zhong),壓(ya)縮(suo)單元的(de)默認大小(xiao)是256KB。
參數
參數可參看:
二、Hive+ORC建(jian)立數據(ju)倉庫
在建Hive表的時候我們就應該指定文件的存儲格式。所以你可以在Hive QL語句里面指定用ORCFile這種文(wen)件格式,如下(xia):
CREATE TABLE ... STORED AS ORC
ALTER TABLE ... [PARTITION partition_spec] SET FILEFORMAT ORC
SET hive.default.fileformat=Orc
所有關于ORCFile的參數都是在(zai)Hive QL語句(ju)的TBLPROPERTIES字段里面出現,他們(men)是:
|
Key |
Default |
Notes |
|
orc.compress |
ZLIB |
high level compression (one of NONE, ZLIB, SNAPPY) |
|
orc.compress.size |
262,144 |
number of bytes in each compression chunk |
|
orc.stripe.size |
268435456 |
number of bytes in each stripe |
|
orc.row.index.stride |
10,000 |
number of rows between index entries (must be >= 1000) |
|
orc.create.index |
true |
whether to create row indexes |
三、Java操作(zuo)ORC
到//orc.apache.org官網(wang)下載orc源碼(ma)包,然后(hou)編(bian)譯(yi)獲取(qu)orc-core-1.3.0.jar、orc-mapreduce-1.3.0.jar、orc-tools-1.3.0.jar,將其加(jia)入項目中
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hive.ql.exec.vector.LongColumnVector;
import org.apache.hadoop.hive.ql.exec.vector.VectorizedRowBatch;
import org.apache.orc.CompressionKind;
import org.apache.orc.OrcFile;
import org.apache.orc.TypeDescription;
import org.apache.orc.Writer;
public class TestORCWriter {
public static void main(String[] args) throws Exception {
Path testFilePath = new Path("/tmp/test.orc");
Configuration conf = new Configuration();
TypeDescription schema = TypeDescription.fromString("struct<field1:int,field2:int,field3:int>");
Writer writer = OrcFile.createWriter(testFilePath, OrcFile.writerOptions(conf).setSchema(schema).compress(CompressionKind.SNAPPY));
VectorizedRowBatch batch = schema.createRowBatch();
LongColumnVector first = (LongColumnVector) batch.cols[0];
LongColumnVector second = (LongColumnVector) batch.cols[1];
LongColumnVector third = (LongColumnVector) batch.cols[2];
final int BATCH_SIZE = batch.getMaxSize();
// add 1500 rows to file
for (int r = 0; r < 15000000; ++r) {
int row = batch.size++;
first.vector[row] = r;
second.vector[row] = r * 3;
third.vector[row] = r * 6;
if (row == BATCH_SIZE - 1) {
writer.addRowBatch(batch);
batch.reset();
}
}
if (batch.size != 0) {
writer.addRowBatch(batch);
batch.reset();
}
writer.close();
}
}
大多(duo)情況下(xia),還是建議在Hive中將(jiang)文(wen)本文(wen)件轉成(cheng)ORC格(ge)式,這種用(yong)JAVA在本地(di)生成(cheng)ORC文(wen)件,屬于特(te)殊需(xu)求場景。
參(can)考:
