/* java
*首先聲明的是:此文純粹是收藏,再看Hive,在建立表的時候有store as (format)其中有一種格式就是RCFile,因此我想了解RCFile究竟是什麼類型的存儲格式,這篇文章寫的很好~~~~~~~ 算法
*/ sql
本文介紹了Facebook公司數據分析系統中的RCFile存儲結構,該結構集行存儲和列存儲的優勢於一身,在MapReduce環境下的大規模數據分析中扮演重要角色。 數據庫
Facebook曾在2010 ICDE(IEEE International Conference on Data Engineering)會議上介紹了數據倉庫Hive。Hive存儲海量數據在Hadoop系統中,提供了一套類數據庫的數據存儲和處理機制。它採用類SQL語言對數據進行自動化管理和處理,通過語句解析和轉換,最終生成基於Hadoop的MapReduce任務,經過執行這些任務完成數據處理。圖1顯示了Hive數據倉庫的系統結構。 apache
圖1 Hive數據倉庫的系統結構 緩存
基於MapReduce的數據倉庫在超大規模數據分析中扮演了重要角色,對於典型的Web服務供應商,這些分析有助於它們快速理解動態的用戶行爲及變化的用戶需求。數據存儲結構是影響數據倉庫性能的關鍵因素之一。Hadoop系統中經常使用的文件存儲格式有支持文本的TextFile和支持二進制的SequenceFile等,它們都屬於行存儲方式。Facebook工程師發表的RCFile: A Fast and Spaceefficient Data Placement Structure in MapReducebased Warehouse Systems一文,介紹了一種高效的數據存儲結構——RCFile(Record Columnar File),並將其應用於Facebook的數據倉庫Hive中。與傳統數據庫的數據存儲結構相比,RCFile更有效地知足了基於MapReduce的數據倉庫的四個關鍵需求,即Fast data loading、Fast query processing、Highly efficient storage space utilization和Strong adaptivity to highly dynamic workload patterns。 網絡
數據倉庫的需求 架構
基於Facebook系統特徵和用戶數據的分析,在MapReduce計算環境下,數據倉庫對於數據存儲結構有四個關鍵需求。 併發
Fast data loading app
對於Facebook的產品數據倉庫而言,快速加載數據(寫數據)是很是關鍵的。天天大約有超過20TB的數據上傳到Facebook的數據倉庫,因爲數據加載期間網絡和磁盤流量會干擾正常的查詢執行,所以縮短數據加載時間是很是必要的。
Fast query processing
爲了知足實時性的網站請求和支持高併發用戶提交查詢的大量讀負載,查詢響應時間是很是關鍵的,這要求底層存儲結構可以隨着查詢數量的增長而保持高速的查詢處理。
Highly efficient storage space utilization
高速增加的用戶活動老是須要可擴展的存儲容量和計算能力,有限的磁盤空間須要合理管理海量數據的存儲。實際上,該問題的解決方案就是最大化磁盤空間利用率。
Strong adaptivity to highly dynamic workload patterns
同一份數據集會供給不一樣應用的用戶,經過各類方式來分析。某些數據分析是例行過程,按照某種固定模式週期性執行;而另外一些則是從中間平臺發起的查詢。大多數負載不遵循任何規則模式,這須要底層系統在存儲空間有限的前提下,對數據處理中不可預知的動態數據具有高度的適應性,而不是專一於某種特殊的負載模式。
MapReduce存儲策略
要想設計並實現一種基於MapReduce數據倉庫的高效數據存儲結構,關鍵挑戰是在MapReduce計算環境中知足上述四個需求。在傳統數據庫系統中,三種數據存儲結構被普遍研究,分別是行存儲結構、列存儲結構和PAX混合存儲結構。上面這三種結構都有其自身特色,不過簡單移植這些數據庫導向的存儲結構到基於MapReduce的數據倉庫系統並不能很好地知足全部需求。
行存儲
如圖2所示,基於Hadoop系統行存儲結構的優勢在於快速數據加載和動態負載的高適應能力,這是由於行存儲保證了相同記錄的全部域都在同一個集羣節點,即同一個HDFS塊。不過,行存儲的缺點也是顯而易見的,例如它不能支持快速查詢處理,由於當查詢僅僅針對多列表中的少數幾列時,它不能跳過沒必要要的列讀取;此外,因爲混合着不一樣數據值的列,行存儲不易得到一個極高的壓縮比,即空間利用率不易大幅提升。儘管經過熵編碼和利用列相關性可以得到一個較好的壓縮比,可是複雜數據存儲實現會致使解壓開銷增大。
圖2 HDFS塊內行存儲的例子
列存儲
圖3顯示了在HDFS上按照列組存儲表格的例子。在這個例子中,列A和列B存儲在同一列組,而列C和列D分別存儲在單獨的列組。查詢時列存儲可以避免讀沒必要要的列,而且壓縮一個列中的類似數據可以達到較高的壓縮比。然而,因爲元組重構的較高開銷,它並不能提供基於Hadoop系統的快速查詢處理。列存儲不能保證同一記錄的全部域都存儲在同一集羣節點,例如圖2的例子中,記錄的4個域存儲在位於不一樣節點的3個HDFS塊中。所以,記錄的重構將致使經過集羣節點網絡的大量數據傳輸。儘管預先分組後,多個列在一塊兒可以減小開銷,可是對於高度動態的負載模式,它並不具有很好的適應性。除非全部列組根據可能的查詢預先建立,不然對於一個查詢須要一個不可預知的列組合,一個記錄的重構或許須要2個或多個列組。再者因爲多個組之間的列交疊,列組可能會建立多餘的列數據存儲,這致使存儲利用率的下降。
圖3 HDFS塊內列存儲的例子
PAX混合存儲
PAX存儲模型(用於Data Morphing存儲技術)使用混合存儲方式,目的在於提高CPU Cache性能。對於記錄中來自不一樣列的多個域,PAX將它們放在一個磁盤頁中。在每一個磁盤頁中,PAX使用一個迷你頁來存儲屬於每一個列的全部域,並使用一個頁頭來存儲迷你頁的指針。相似於行存儲,PAX對多種動態查詢有很強的適應能力。然而,它並不能知足大型分佈式系統對於高存儲空間利用率和快速查詢處理的需求,緣由在於:首先,PAX沒有數據壓縮的相關工做,這部分與Cache優化關係不大,但對於大規模數據處理系統是很是關鍵的,它提供了列維度數據壓縮的可能性;其次,PAX不能提高I/O性能,由於它不能改變實際的頁內容,該限制使得大規模數據掃描時不易實現快速查詢處理;再次,PAX用固定的頁做爲數據組織的基本單位,按照這個大小,在海量數據處理系統中,PAX將不會有效存儲不一樣大小類型的數據域。本文介紹的是RCF i l e 數據存儲結構在Hadoop系統上的實現。該結構強調:第一,RCFile存儲的表是水平劃分的,分爲多個行組, 每一個行組再被垂直劃分, 以便每列單獨存儲;第二,RCFile在每一個行組中利用一個列維度的數據壓縮,並提供一種Lazy解壓(decompression)技術來在查詢執行時避免沒必要要的列解壓;第三,RCFile支持彈性的行組大小,行組大小須要權衡數據壓縮性能和查詢性能兩方面。
RCFile的設計與實現
RCFile(Record Columnar File)存儲結構遵循的是「先水平劃分,再垂直劃分」的設計理念,這個想法來源於PAX。它結合了行存儲和列存儲的優勢:首先,RCFile保證同一行的數據位於同一節點,所以元組重構的開銷很低;其次,像列存儲同樣,RCFile可以利用列維度的數據壓縮,而且能跳過沒必要要的列讀取。圖4是一個HDFS塊內RCFile方式存儲的例子。
圖4 HDFS塊內RCFile方式存儲的例子
數據格式
RCFile在HDFS分佈式文件系統之上設計並實現,如圖4所示,RCFile按照下面的數據格式來存儲一張表。
RCFile基於HDFS架構,表格佔用多個HDFS塊。
每一個HDFS塊中,RCFile以行組爲基本單位來組織記錄。也就是說,存儲在一個HDFS塊中的全部記錄被劃分爲多個行組。對於一張表,全部行組大小都相同。一個HDFS塊會有一個或多個行組。
一個行組包括三個部分。第一部分是行組頭部的同步標識,主要用於分隔HDFS塊中的兩個連續行組;第二部分是行組的元數據頭部,用於存儲行組單元的信息,包括行組中的記錄數、每一個列的字節數、列中每一個域的字節數;第三部分是表格數據段,即實際的列存儲數據。在該部分中,同一列的全部域順序存儲。從圖4能夠看出,首先存儲了列A的全部域,而後存儲列B的全部域等。
壓縮方式
RCFile的每一個行組中,元數據頭部和表格數據段分別進行壓縮。
對於全部元數據頭部,RCFile使用RLE(Run Length Encoding)算法來壓縮數據。因爲同一列中全部域的長度值都順序存儲在該部分,RLE算法可以找到重複值的長序列,尤爲對於固定的域長度。
表格數據段不會做爲整個單元來壓縮;相反每一個列被獨立壓縮,使用Gzip壓縮算法。RCFile使用重量級的Gzip壓縮算法,是爲了得到較好的壓縮比,而不使用RLE算法的緣由在於此時列數據非排序。此外,因爲Lazy壓縮策略,當處理一個行組時,RCFile不須要解壓全部列。所以,相對較高的Gzip解壓開銷能夠減小。
儘管RCFile對錶格數據的全部列使用一樣的壓縮算法,不過若是使用不一樣的算法來壓縮不一樣列或許效果會更好。RCFile未來的工做之一可能就是根據每列的數據類型和數據分佈來自適應選擇最好的壓縮算法。
數據追加
RCFile不支持任意方式的數據寫操做,僅提供一種追加接口,這是由於底層的HDFS當前僅僅支持數據追加寫文件尾部。數據追加方法描述以下。
RCFile爲每列建立並維護一個內存column holder,當記錄追加時,全部域被分發,每一個域追加到其對應的column holder。此外,RCFile在元數據頭部中記錄每一個域對應的元數據。
RCFile提供兩個參數來控制在刷寫到磁盤以前,內存中緩存多少個記錄。一個參數是記錄數的限制,另外一個是內存緩存的大小限制。
RCFile首先壓縮元數據頭部並寫到磁盤,而後分別壓縮每一個column holder,並將壓縮後的column holder刷寫到底層文件系統中的一個行組中。
數據讀取和Lazy解壓
在MapReduce框架中,mapper將順序處理HDFS塊中的每一個行組。當處理一個行組時,RCFile無需所有讀取行組的所有內容到內存。
相反,它僅僅讀元數據頭部和給定查詢須要的列。所以,它能夠跳過沒必要要的列以得到列存儲的I/O優點。例如,表tbl(c1, c2, c3, c4)有4個列,作一次查詢「SELECT c1 FROM tbl WHERE c4 = 1」,對每一個行組,RCFile僅僅讀取c1和c4列的內容。在元數據頭部和須要的列數據加載到內存中後,它們須要解壓。元數據頭部總會解壓並在內存中維護直到RCFile處理下一個行組。然而,RCFile不會解壓全部加載的列,相反,它使用一種Lazy解壓技術。
Lazy解壓意味着列將不會在內存解壓,直到RCFile決定列中數據真正對查詢執行有用。因爲查詢使用各類WHERE條件,Lazy解壓很是有用。若是一個WHERE條件不能被行組中的全部記錄知足,那麼RCFile將不會解壓WHERE條件中不知足的列。例如,在上述查詢中,全部行組中的列c4都解壓了。然而,對於一個行組,若是列c4中沒有值爲1的域,那麼就無需解壓列c1。
行組大小
I/O性能是RCFile關注的重點,所以RCFile須要行組夠大而且大小可變。行組大小和下面幾個因素相關。
行組大的話,數據壓縮效率會比行組小時更有效。根據對Facebook平常應用的觀察,當行組大小達到一個閾值後,增長行組大小並不能進一步增長Gzip算法下的壓縮比。
行組變大可以提高數據壓縮效率並減小存儲量。所以,若是對縮減存儲空間方面有強烈需求,則不建議選擇使用小行組。須要注意的是,當行組的大小超過4MB,數據的壓縮比將趨於一致。
儘管行組變大有助於減小表格的存儲規模,可是可能會損害數據的讀性能,由於這樣減小了Lazy解壓帶來的性能提高。並且行組變大會佔用更多的內存,這會影響併發執行的其餘MapReduce做業。考慮到存儲空間和查詢效率兩個方面,Facebook選擇4MB做爲默認的行組大小,固然也容許用戶自行選擇參數進行配置。
小結
本文簡單介紹了RCFile存儲結構,其普遍應用於Facebook公司的數據分析系統Hive中。首先,RCFile具有至關於行存儲的數據加載速度和負載適應能力;其次,RCFile的讀優化能夠在掃描表格時避免沒必要要的列讀取,測試顯示在多數狀況下,它比其餘結構擁有更好的性能;再次,RCFile使用列維度的壓縮,所以可以有效提高存儲空間利用率。
爲了提升存儲空間利用率,Facebook各產品線應用產生的數據從2010年起均採用RCFile結構存儲,按行存儲(SequenceFile/TextFile)結構保存的數據集也轉存爲RCFile格式。此外,Yahoo公司也在Pig數據分析系統中集成了RCFile,RCFile正在用於另外一個基於Hadoop的數據管理系統Howl(http://wiki.apache.org/pig/Howl)。並且,根據Hive開發社區的交流,RCFile也成功整合加入其餘基於MapReduce的數據分析平臺。有理由相信,做爲數據存儲標準的RCFile,將繼續在MapReduce環境下的大規模數據分析中扮演重要角色。
/**
我在這裏補充hive 的其餘存儲格式
*/
hive文件存儲格式包括如下幾類:
TEXTFILe
SEQUENCEFILE
- RCFILE
其中TEXTFILE爲默認格式,建表時不指定默認爲這個格式,導入數據時會直接把數據文件拷貝到hdfs上不進行處理
SequenceFile,RCFile格式的表不能直接從本地文件導入數據,數據要先導入到textfile格式的表中,而後再從textfile表中用insert導入到SequenceFile,RCFile表中。
TEXTFIEL
默認格式,數據不作壓縮,磁盤開銷大,數據解析開銷大。
可結合Gzip、Bzip2使用(系統自動檢查,執行查詢時自動解壓),但使用這種方式,hive不會對數據進行切分,從而沒法對數據進行並行操做。
實例:
- > create table test1(str STRING)
- > STORED AS TEXTFILE;
- OK
- Time taken: 0.786 seconds
- #寫腳本生成一個隨機字符串文件,導入文件:
- > LOAD DATA LOCAL INPATH '/home/work/data/test.txt' INTO TABLE test1;
- Copying data from file:/home/work/data/test.txt
- Copying file: file:/home/work/data/test.txt
- Loading data to table default.test1
- OK
- Time taken: 0.243 seconds
> create table test1(str STRING) > STORED AS TEXTFILE; OK Time taken: 0.786 seconds #寫腳本生成一個隨機字符串文件,導入文件: > LOAD DATA LOCAL INPATH '/home/work/data/test.txt' INTO TABLE test1; Copying data from file:/home/work/data/test.txt Copying file: file:/home/work/data/test.txt Loading data to table default.test1 OK Time taken: 0.243 seconds
SEQUENCEFILE
SequenceFile是Hadoop API提供的一種二進制文件支持,其具備使用方便、可分割、可壓縮的特色。
SequenceFile支持三種壓縮選擇:NONE, RECORD, BLOCK。 Record壓縮率低,通常建議使用BLOCK壓縮。
示例:
- > create table test2(str STRING)
- > STORED AS SEQUENCEFILE;
- OK
- Time taken: 5.526 seconds
- hive> SET hive.exec.compress.output=true;
- hive> SET io.seqfile.compression.type=BLOCK;
- hive> INSERT OVERWRITE TABLE test2 SELECT * FROM test1;
> create table test2(str STRING) > STORED AS SEQUENCEFILE; OK Time taken: 5.526 seconds hive> SET hive.exec.compress.output=true; hive> SET io.seqfile.compression.type=BLOCK; hive> INSERT OVERWRITE TABLE test2 SELECT * FROM test1;
RCFILE
RCFILE是一種行列存儲相結合的存儲方式。首先,其將數據按行分塊,保證同一個record在一個塊上,避免讀一個記錄須要讀取多個block。其次,塊數據列式存儲,有利於數據壓縮和快速的列存取。RCFILE文件示例:
- > create table test3(str STRING)
- > STORED AS RCFILE;
- OK
- Time taken: 0.184 seconds
- > INSERT OVERWRITE TABLE test3 SELECT * FROM test1;
> create table test3(str STRING) > STORED AS RCFILE; OK Time taken: 0.184 seconds > INSERT OVERWRITE TABLE test3 SELECT * FROM test1;
自定義格式
當用戶的數據文件格式不能被當前 Hive 所識別的時候,能夠自定義文件格式。
用戶能夠經過實現inputformat和 outputformat來自定義輸入輸出格式,參考代碼:.\hive-0.8.1\src\contrib\src\java\org\apache \hadoop\hive\contrib\fileformat\base64
實例:
- > stored as
- > inputformat 'org.apache.hadoop.hive.contrib.fileformat.base64.Base64TextInputFormat'
- > outputformat 'org.apache.hadoop.hive.contrib.fileformat.base64.Base64TextOutputFormat';
> create table test4(str STRING) > stored as > inputformat 'org.apache.hadoop.hive.contrib.fileformat.base64.Base64TextInputFormat' > outputformat 'org.apache.hadoop.hive.contrib.fileformat.base64.Base64TextOutputFormat';
- aGVsbG8saGl2ZQ==
- aGVsbG8sd29ybGQ=
- aGVsbG8saGFkb29w
$ cat test1.txt aGVsbG8saGl2ZQ== aGVsbG8sd29ybGQ= aGVsbG8saGFkb29w
test1文件爲base64編碼後的內容,decode後數據爲:
- hello,world
- hello,hadoop
hello,hive hello,world hello,hadoop
load數據並查詢:
- Copying data from file:/home/work/test1.txt
- Copying file: file:/home/work/test1.txt
- Loading data to table default.test4
- OK
- Time taken: 4.742 seconds
- hive> select * from test4;
- OK
- hello,hive
- hello,world
- hello,hadoop
- Time taken: 1.953 seconds
hive> LOAD DATA LOCAL INPATH '/home/work/test1.txt' INTO TABLE test4; Copying data from file:/home/work/test1.txt Copying file: file:/home/work/test1.txt Loading data to table default.test4 OK Time taken: 4.742 seconds hive> select * from test4; OK hello,hive hello,world hello,hadoop Time taken: 1.953 seconds
總結
相比TEXTFILE和SEQUENCEFILE,RCFILE因爲列式存儲方式,數據加載時性能消耗較大,可是具備較好的壓縮比和查詢響應。數據倉庫的特色是一次寫入、屢次讀取,所以,總體來看,RCFILE相比其他兩種格式具備較明顯的優點。