轉自:http://www.lai18.com/content/24596525.html?from=cancelphp
ORC文件格式是從Hive-0.11版本開始的。關於ORC文件格式的官方文檔,以及基於官方文檔的翻譯內容這裏就不贅述了,有興趣的能夠仔細研究瞭解一下。本文接下來根據論文《Major Technical Advancements in Apache Hive》中的內容進行深刻的研究。
html
ORC的全稱是(Optimized Record Columnar),使用ORC文件格式能夠提升hive讀、寫和處理數據的能力。ORC在RCFile的基礎上進行了必定的改進,因此與RCFile相比,具備如下一些優點:
- 一、ORC中的特定的序列化與反序列化操做可使ORC file writer根據數據類型進行寫出。
- 二、提供了多種RCFile中沒有的indexes,這些indexes可使ORC的reader很快的讀到須要的數據,而且跳過無用數據,這使得ORC文件中的數據能夠很快的獲得訪問。
- 三、因爲ORC file writer能夠根據數據類型進行寫出,因此ORC能夠支持複雜的數據結構(好比Map等)。
- 四、除了上面三個理論上就具備的優點以外,ORC的具體實現上還有一些其餘的優點,好比ORC的stripe默認大小更大,爲ORC writer提供了一個memory manager來管理內存使用狀況。
圖1-ORC文件結構圖
linux
在ORC格式的hive表中,記錄首先會被橫向的切分爲多個stripes,而後在每個stripe內數據以列爲單位進行存儲,全部列的內容都保存在同一個文件中。每一個stripe的默認大小爲256MB,相對於RCFile每一個4MB的stripe而言,更大的stripe使ORC的數據讀取更加高效。
對於複雜數據類型,好比Map,ORC文件會將一個複雜數據類型字段解析成多個子字段。下表中列舉了ORC文件中對於複雜數據類型的解析
apache
Data type | Chile columns |
---|---|
Array | 一個包含全部數組元素的子字段 |
Map | 兩個子字段,一個key字段,一個value字段 |
Struct | 每個屬性對應一個子字段 |
Union | 每個屬性對應一個子字段 |
當字段類型都被解析後,會由這些字段類型組成一個字段樹,只有樹的葉子節點纔會保存表數據,這些葉子節點中的數據造成一個數據流,如上圖中的Data Stream。
爲了使ORC文件的reader更加高效的讀取數據,字段的metadata會保存在Meta Stream中。在字段樹中,每個非葉子節點記錄的就是字段的metadata,好比對一個array來講,會記錄它的長度。下圖根據表的字段類型生成了一個對應的字段樹。
圖二-字段樹結構圖
在Hive-0.13中,ORC文件格式只支持讀取指定字段,還不支持只讀取特殊字段類型中的指定部分。
使用ORC文件格式時,用戶可使用HDFS的每個block存儲ORC文件的一個stripe。對於一個ORC文件來講,stripe的大小通常須要設置得比HDFS的block小,若是不這樣的話,一個stripe就會分別在HDFS的多個block上,當讀取這種數據時就會發生遠程讀數據的行爲。若是設置stripe的只保存在一個block上的話,若是當前block上的剩餘空間不足以存儲下一個strpie,ORC的writer接下來會將數據打散保存在block剩餘的空間上,直到這個block存滿爲止。這樣,下一個stripe又會從下一個block開始存儲。
數組
在ORC文件中添加索引是爲了更加高效的從HDFS讀取數據。在ORC文件中使用的是稀疏索引(sparse indexes)。在ORC文件中主要有兩種用途的索引,一個是數據統計(Data Statistics)索引,一個是位置指針(Position Pointers)索引。
數據結構
ORC reader用這個索引來跳過讀取沒必要要的數據,在ORC writer生成ORC文件時會建立這個索引文件。這個索引中統計的信息主要有記錄的條數,記錄的max, min, sum值,以及對text類型和binary類型字段還會記錄其長度。對於複雜數據類型,好比Array, Map, Struct, Union,它們的子字段中也會記錄這些統計信息。
在ORC文件中,Data Statistics有三個level。
(1)file level statistics
在ORC文件的末尾會記錄文件級別的統計信息,會記錄整個文件中columns的統計信息。這些信息主要用於查詢的優化,也能夠爲一些簡單的聚合查詢好比max, min, sum輸出結果。
(2)stripe level statistics
ORC文件會保存每一個字段stripe級別的統計信息,ORC reader使用這些統計信息來肯定對於一個查詢語句來講,須要讀入哪些stripe中的記錄。好比說某個stripe的字段max(a)=10,min(a)=3,那麼當where條件爲a >10或者a <3時,那麼這個stripe中的全部記錄在查詢語句執行時不會被讀入。
(3)index group level statistics
爲了進一步的避免讀入沒必要要的數據,在邏輯上將一個column的index以一個給定的值(默認爲10000,可由參數配置)分割爲多個index組。以10000條記錄爲一個組,對數據進行統計。Hive查詢引擎會將where條件中的約束傳遞給ORC reader,這些reader根據組級別的統計信息,過濾掉沒必要要的數據。若是該值設置的過小,就會保存更多的統計信息,用戶須要根據本身數據的特色權衡一個合理的值。
併發
當讀取一個ORC文件時,ORC reader須要有兩個位置信息才能準確的進行數據讀取操做。
(1)metadata streams和data streams中每一個group的開始位置
因爲每一個stripe中有多個group,ORC reader須要知道每一個group的metadata streams和data streams的開始位置。圖1中右邊的虛線表明的就是這種pointer。
(2)stripes的開始位置
因爲一個ORC文件能夠包含多個stripes,而且一個HDFS block也能包含多個stripes。爲了快速定位指定stripe的位置,須要知道每一個stripe的開始位置。這些信息會保存在ORC file的File Footer中。如圖1中間位置的虛線所示。
app
ORC文件使用兩級壓縮機制,首先將一個數據流使用流式編碼器進行編碼,而後使用一個可選的壓縮器對數據流進行進一步壓縮。
一個column可能保存在一個或多個數據流中,能夠將數據流劃分爲如下四種類型:
• Byte Stream
字節流保存一系列的字節數據,不對數據進行編碼。
• Run Length Byte Stream
字節長度字節流保存一系列的字節數據,對於相同的字節,保存這個重複值以及該值在字節流中出現的位置。
• Integer Stream
整形數據流保存一系列整形數據。能夠對數據量進行字節長度編碼以及delta編碼。具體使用哪一種編碼方式須要根據整形流中的子序列模式來肯定。
• Bit Field Stream
比特流主要用來保存boolean值組成的序列,一個字節表明一個boolean值,在比特流的底層是用Run Length Byte Stream來實現的。
接下來會以Integer和String類型的字段舉例來講明。
(1)Integer
對於一個整形字段,會同時使用一個比特流和整形流。比特流用於標識某個值是否爲null,整形流用於保存該整形字段非空記錄的整數值。
(2)String
對於一個String類型字段,ORC writer在開始時會檢查該字段值中不一樣的內容數佔非空記錄總數的百分比不超過0.8的話,就使用字典編碼,字段值會保存在一個比特流,一個字節流及兩個整形流中。比特流也是用於標識null值的,字節流用於存儲字典值,一個整形流用於存儲字典中每一個詞條的長度,另外一個整形流用於記錄字段值。
若是不能用字典編碼,ORC writer會知道這個字段的重複值太少,用字典編碼效率不高,ORC writer會使用一個字節流保存String字段的值,而後用一個整形流來保存每一個字段的字節長度。
在ORC文件中,在各類數據流的底層,用戶能夠自選ZLIB, Snappy和LZO壓縮方式對數據流進行壓縮。編碼器通常會將一個數據流壓縮成一個個小的壓縮單元,在目前的實現中,壓縮單元的默認大小是256KB。
ide
當ORC writer寫數據時,會將整個stripe保存在內存中。因爲stripe的默認值通常比較大,當有多個ORC writer同時寫數據時,可能會致使內存不足。爲了如今這種併發寫時的內存消耗,ORC文件中引入了一個內存管理器。在一個Map或者Reduce任務中內存管理器會設置一個閾值,這個閾值會限制writer使用的總內存大小。當有新的writer須要寫出數據時,會向內存管理器註冊其大小(通常也就是stripe的大小),當內存管理器接收到的總註冊大小超過閾值時,內存管理器會將stripe的實際大小按該writer註冊的內存大小與總註冊內存大小的比例進行縮小。當有writer關閉時,內存管理器會將其註冊的內存從總註冊內存中註銷。
post
參數名 | 默認值 | 說明 |
---|---|---|
hive.exec.orc.default.stripe.size | 256*1024*1024 | stripe的默認大小 |
hive.exec.orc.default.block.size | 256*1024*1024 | orc文件在文件系統中的默認block大小,從hive-0.14開始 |
hive.exec.orc.dictionary.key.size.threshold | 0.8 | String類型字段使用字典編碼的閾值 |
hive.exec.orc.default.row.index.stride | 10000 | stripe中的分組大小 |
hive.exec.orc.default.compress | ZLIB | ORC文件的默認壓縮方式 |
hive.exec.orc.skip.corrupt.data | false | 遇到錯誤數據的處理方式,false直接拋出異常,true則跳過該記錄 |
更多參數可參看:https://cwiki.apache.org/confluence/display/Hive/Configuration+Properties#ConfigurationProperties-ORCFileFormat
關於ORC文件存儲格式的實際案例分析,能夠參考文章Hive-ORC文件存儲格式(續)
其餘文章:https://my.oschina.net/u/270950/blog/167400
http://www.linuxidc.com/Linux/2014-06/103421.htm
http://xn--jlq582ax31c.xn--fiqs8s/post/184
http://www.itweet.cn/2016/03/15/columnar-storage-parquet-and-orc/
http://www.aboutyun.com/home.php?mod=space&uid=87&do=blog&id=3087