Hive-ORC文件存儲格式

原文鏈接:http://www.lai18.com/content/24596525.html?from=cancel

Hive-ORC文件存儲格式

轉自:http://www.lai18.com/content/24596525.html?from=cancel

ORC文件格式是從Hive-0.11版本開始的。關於ORC文件格式的官方文檔,以及基於官方文檔的翻譯內容這裏就不贅述了,有興趣的可以仔細研究瞭解一下。本文接下來根據論文《Major Technical Advancements in Apache Hive》中的內容進行深入的研究。
 

一、ORC文件格式

  ORC的全稱是(Optimized Record Columnar),使用ORC文件格式可以提高hive讀、寫和處理數據的能力。ORC在RCFile的基礎上進行了一定的改進,所以與RCFile相比,具有以下一些優勢: 

- 1、ORC中的特定的序列化與反序列化操作可以使ORC file writer根據數據類型進行寫出。 

- 2、提供了多種RCFile中沒有的indexes,這些indexes可以使ORC的reader很快的讀到需要的數據,並且跳過無用數據,這使得ORC文件中的數據可以很快的得到訪問。 

- 3、由於ORC file writer可以根據數據類型進行寫出,所以ORC可以支持複雜的數據結構(比如Map等)。 

- 4、除了上面三個理論上就具有的優勢之外,ORC的具體實現上還有一些其他的優勢,比如ORC的stripe默認大小更大,爲ORC writer提供了一個memory manager來管理內存使用情況。 




  圖1-ORC文件結構圖
 

二、ORC數據存儲方法

  在ORC格式的hive表中,記錄首先會被橫向的切分爲多個stripes,然後在每一個stripe內數據以列爲單位進行存儲,所有列的內容都保存在同一個文件中。每個stripe的默認大小爲256MB,相對於RCFile每個4MB的stripe而言,更大的stripe使ORC的數據讀取更加高效。 

  對於複雜數據類型,比如Map,ORC文件會將一個複雜數據類型字段解析成多個子字段。下表中列舉了ORC文件中對於複雜數據類型的解析
 

 
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)索引。
 

1. Data Statistics

  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根據組級別的統計信息,過濾掉不必要的數據。如果該值設置的太小,就會保存更多的統計信息,用戶需要根據自己數據的特點權衡一個合理的值。 

  
 

3. Position Pointers

  當讀取一個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中間位置的虛線所示。
 

四、文件壓縮

  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。
 

五、內存管理

  當ORC writer寫數據時,會將整個stripe保存在內存中。由於stripe的默認值一般比較大,當有多個ORC writer同時寫數據時,可能會導致內存不足。爲了現在這種併發寫時的內存消耗,ORC文件中引入了一個內存管理器。在一個Map或者Reduce任務中內存管理器會設置一個閾值,這個閾值會限制writer使用的總內存大小。當有新的writer需要寫出數據時,會向內存管理器註冊其大小(一般也就是stripe的大小),當內存管理器接收到的總註冊大小超過閾值時,內存管理器會將stripe的實際大小按該writer註冊的內存大小與總註冊內存大小的比例進行縮小。當有writer關閉時,內存管理器會將其註冊的內存從總註冊內存中註銷。
 

六、參數

 
參數名 默認值 說明
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.bitstech.net/2016/09/26/parquet%E4%B8%8Eorc%EF%BC%9A%E9%AB%98%E6%80%A7%E8%83%BD%E5%88%97%E5%BC%8F%E5%AD%98%E5%82%A8%E6%A0%BC%E5%BC%8F/

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

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