從NSM到Parquet:儲存結構的衍化

白喬發表於2015-03-10

http://blog.csdn.net/dc_726/article/details/41777661

為了優化MapReduceMR之前的各種工具的效能,在Hadoop內建的資料儲存格式外,又湧現了一批各種各樣的儲存方式。如優化Hive效能的RCFile,以及配合Impala實現出Google Dremel功能(類似甚至是功能的超集)Parquet等。今天就來一起學習一下HDFS中資料儲存的進化歷程。

資料擺放結構

資料擺放結構(data placement structure),顧名思義,就是資料如何在HDFS中放置和儲存的。這種擺放結構對於像Hive這種,HDFS之上的查詢工具來說是非常重要的,擺放的結構和策略會直接影響Hive查詢引擎的實現和效能。從Hive的角度來看,資料擺放結構就是:怎樣從Hive中關係表的邏輯檢視對映到HDFS塊資料的物理儲存


從更高的層次來看,不僅僅是HDFS這種分散式系統上的應用,data placement對於傳統資料庫、NoSQL等系統也都是很重要的:


通常來說,有以下三種資料擺放結構:

Ø  水平的行儲存結構

Ø  垂直的列儲存結構

Ø  混合型的儲存結構

下面就依次看一下這三種儲存方式的優缺點。

水平的行儲存結構

行儲存是最傳統的儲存方式,經典模型是NSM(The N-ary Storage Model),其優缺點也很明顯。優點就是資料載入非常快,因為一行資料都是放在一起的。同時對各種動態workload有很強的適應能力(具體指?)。而缺點就是:

Ø  因為無法避免讀取不必要的列,而無法提供海量資料的高效能查詢。

Ø  此外,由於混合儲存了不同型別的資料列,實現高壓縮也很不容易。

下圖是NSM的典型實現,主要由page headerbody(資料),以及trailer(每行資料在當前page中位置的偏移量)。下圖中還指出了一個缺點,就是由於每次都載入了不必要的列,導致快取中塞滿了無用資料。


下面來看兩個NSM的例子。首先是MySQLInnodb引擎,InnoDBtablespace模仿了Oracle中的概念,而page結構(page layout, page structurerow format)類似NSM模型。我們主要關注其中的page結構,其他row-based的資料庫也都是類似的儲存結構。



再來看一下Hadoop的例子。我們最常使用的兩種格式就是TextFileSequenceFile,它們都是按行儲存。TextFile讀起來很方便,但比較佔空間,Gzip壓縮後不支援塊分離。Hadoop預設內部使用SequenceFile二進位制儲存,支援可分離的壓縮演算法。同時,由於當我們把檔案寫入HDFS時會分成block塊,讀取時是整塊讀取後按分隔符解析,逐行傳送給map任務(HDFS就是為流式讀取大檔案而設計),不存在RDBMS中的隨機讀一行,所以block尾部不需要trailer部分來儲存偏移量


垂直的列儲存結構

列儲存彌補了行儲存的兩個劣勢,可以只讀取目標列的資料,並提供高壓縮比。但是缺點是:

Ø  由於資料儲存的分散,查詢時會產生高昂的資料重建(tuple reconstruction)開銷。

Ø  並且更新、刪除等對資料的修改操作也會比較麻煩。

典型的實現是DSM模型,在1985年就已經提出來了。


下圖就是HDFS中列式儲存的樣子。


現今有很多列式儲存的NoSQL資料庫,在Hadoop中最典型的例子就是HBase了。(待補充:HFile結構,以及HBase如何解決列式儲存的效能開銷等問題)

混合型的儲存結構

PAX(The Partition Attributes Across Model)是一種典型的混合型實現,與前面兩種傳統儲存方式的具體模型比較:


引用一篇文章

NSMN-ary Storage Model),即基於行的儲存模型。隨著硬體的發展,NSM對於快取的利用率較低。NSM在每個磁碟頁面中連續的儲存記錄,使相對頁面的偏移記錄每條記錄的開始。

DSMDecomposition Storage Model)。列儲存模型並不是一個新鮮的概念,在1985年就已經提出,2005年左右隨著資料分析應用的廣泛開展獲得新生。對資料的使用,特別是分析的需求,常常只使用一條記錄的一部分資料。為了減少IO的消耗,提出了“分解儲存模型”。DSM將關係垂直分為n個子關係,屬性僅當需要時才加以存取訪問。對於涉及多個屬性的查詢來說需要額外的開銷用於連線子關係。

PAXPartition Attribute Across)。PAX是記錄在頁面中的混合佈局方式,結合了NSMDSM的優點,避免了對主存不需要的訪問。PAX首先將盡可能多的關係記錄採用NSM方式加以儲存。在每個頁面內,使用按屬性和minipage進行類似於DSM的儲存。在順序掃描時,PAX充分利用了快取的資源。同時,所有的記錄都位於相同的頁面。對於記錄的重構操作,僅僅在minipage之間進行,並不涉及跨頁的操作。相對於DSM來說,對於多屬性的查詢來說PAX優於DSM,因為DSM需要更多的跨頁重構時間。

混合儲存模型,我們可以將所有的資料都理解為由Key/Value/Descriptioncolumn name)構成的三元組儲存模型。KV模型允許你按照你想要的模式來組織資料的儲存,如果應用總是按照行來訪問的(比如總是訪問某個使用者的大部分資料),那麼就可以把資料按照同一個Key組織在一起(實際上就是NSM),而如果某個應用總是分析彙總查詢,可以按照Descriptioncolumn name)將資料組織在一起(DSM或者PAX的實現)。

Record Columnar File(RCFile)借鑑了PAX儲存模型,混合了行式和列式儲存。通過先進行水平分割槽,再垂直分割槽,並且保證同一行的資料一定在同一個結點


RCFile基於HDFS,一個表可以包含多個塊,每塊內按行組(row group)進行組織。每個行組包含:用來分隔行組的sync標記,後設資料頭,以及按列式儲存的表資料。其中後設資料頭和表資料是分別獨立壓縮的。後設資料頭使用RLE(runtime length encoding)演算法,而表資料使用gzip演算法,並配合延遲解壓技術(lazy decompression)RCFile只支援追加(append)寫資料。

Parquet

ParquetClouderaTwitter合作的專案,實現了Dremel論文中定義的資料模型,能夠以列式儲存的二維表來表示巢狀記錄,同時也支援像PigHive等行式查詢引擎。Parquet的儲存結構與RCFile有雷同之處,例如RowGroup包含多個column,而每個column則由page組成,page中的每一項是由repetition leveldefinition levelvalue組成的三元組。


Parquet中使用多種編碼壓縮技術。首先,對於不重複值較少的列可以進行字典編碼(dictionary encoding),例如不重複值<5w個,這要比gzip, lzo, snappy等重型演算法要更好、更快。此外,對於字典編碼後的列值,repetitiondefinition level這種小整數,還可以進行位壓縮(bit packing),用能夠裝下這些小整數的最少的位來儲存它們。最後,結合著前兩種方法,還可以進一步進行RLE(run length encoding)壓縮,這對definition level這種比較稀疏的列來說效果比較好。


參考資料

1 RCFile: A Fast and Space-efficient Data Placement Structure

2 A Multi-resolution Block Storage Model for Database Design

3 Data Page Layouts for Relational Databases on Deep Memory Hierarchies

4 InnoDB Internals: InnoDB File Formats and Source Code Structure

5 Parquet: An Open Columnar Storage for Hadoop


相關文章