大數據存儲格式-parquet

大數據存儲格式-parquet


爲何須要列式存儲

首先咱們從關係數據庫入手,來看關係數據庫的一些常見查詢。對於關係數據庫而言,咱們常見的查詢通常有詳情查詢或者統計分組,可是若是是大數據量的狀況下,關係數據庫是不能很好的支持統計類的查詢,因此通常關係數據庫多有於對OLTP業務,那麼常見的大數據的查詢有個特色,因爲數據量很大,獲取具體的詳情數據意義不大,因此基本都是統計類的查詢,如:select count(1) cnt,ip from access_log group by ip,查詢每一個ip的訪問次數。固然也可能有查詢詳細作深度的數據分析。html

對於查詢速度固然是越快越好,咱們能夠從如下幾個方面來提升這個系統的查詢速度(固然緩存不在考慮的範疇內),1.查詢系統框架的優化,這裏可能包含了(執行計劃啊,分佈式計算等等等),2.底層文件存儲格式的優化,儘可能減小IO.3.固然還有索引技術.sql

針對上面的sql:select count(1) cnt,ip from access_log group by ip數據庫

咱們假設access_log的格式以下: <code> access_log{ string ip; string access_time; ............(其餘N個屬性)apache

} </code>緩存

若是是行存儲:數據結構

咱們須要讀取一行的全部數據,而後獲取其中的ip字段,在作分組統計。增長的磁盤的IO,同時也增長了計算壓力.框架

若是是列存儲會如何: 分佈式

對於上面的統計,咱們只須要讀取IP就能夠,讀取不須要的列信息,這就是列存儲對於大數據的統計類查詢的優勢所在,固然除此以外大數據自己的稀疏性,採用列式可能更好的去優化存儲結構,減小存儲空間.大數據

parquet介紹

parquet是twitter在2013年開源的數據結構,google的Dremel: [Interactive Analysis of Web-Scale Datasets http://research.google.com/pubs/pub36632.html](Interactive Analysis of Web-Scale Datasets http://research.google.com/pubs/pub36632.html "Interactive Analysis of Web-Scale Datasets http://research.google.com/pubs/pub36632.html").這個大數據查詢利器的paper裏面,其實主要也是在闡述底層文件存儲格式。優化

Parquet支持複雜嵌套的數據結構組成,並使用重複級別/定義級別(repetition/definition level )的方法來對數據結構進行編碼,嵌套的方式其實能夠避免了大數據的join問題.

Parquet支持對某一列數據進行壓縮,支持任意開發語言的讀寫操做.目前是apache的頂級項目.

parquet文件格式分析

首先來看一下如何定義一個parquet的文件格式,這裏也是採用相似PB的格式定義 這裏採用了班級信息來做爲示例,有多個班級,每個班級有個master,有多個學生(能夠無),每一個學生有名稱和多個愛好,還有每一門可課程的成績以及課程名稱. schema定義: <code> message classroom{ required string master; repeated group students{ required string name; repeated string hobbys; repeated group coursescore{ required string name; optional string score; } } } </code> required 表示必填 repeated 表示能夠有任意個 optional 0 or 1 對於數據能夠關係能夠分爲Map以及List,若是爲List能夠採用repeated,Map採用group 關鍵字修飾.

這裏咱們來定義一組數據:

<code> { master:"jack", student: name:"tom" student: name:"joy", hobbys:"basketball", hobbys:"football", coursescore: name:"math", coursescore: name:"chinese", score:100 } { master:"BoBo" } </code>

兩個班級一個有學生一個沒有,一個學生有愛好有課程,一個什麼也沒有. 咱們先來看看如何存儲.

存儲

依據上面定義的schema,能夠先轉化爲一個tree表示結構

只有樹的根節點是須要實際存儲的數據節點,其他的只是關係的一種維繫。 下圖展現了其嵌套關係

實際存儲也是這樣,每一列存儲了全部的數據信息。是否是存儲很容易。

讀取

既然全部的同一類的數據存儲在一塊兒,那麼數據如何還原爲原來的數據。這裏引入了parquet的元數據信息,如何還原數據須要 Repetition Level以及Definition Level這兩個元數據信息。

首先咱們須要知道哪些數據是一組的,其實還須要知道數據和數據之間的層級關係,OK。這兩個元數據信息能夠幫咱們搞的.(固然也是存儲的時候寫入的元數據信息)

Repetition Level是記錄該列的值是在哪個級別上重複的。

用剛纔的兩個classroom信息來舉例: 對於兩個classroom的master來講,因爲都是獨立的沒有直接關係,因此他們的Repetition level是0

Jack 0

BoBO 0

對於jack的學生tom,joy來講,tom是第一個學生,因此level是0,而joy平級,因此是1.

<table> <tr><td>master</td><td>Repetition Level</td><tr> <tr><td>Jack</td><td>0</td><tr> <tr><td>BoBo</td><td>0</td><tr> </table>

<table> <tr><td>student.name</td><td>Repetition Level</td><tr> <tr><td>tom</td><td>0</td><tr> <tr><td>joy</td><td>1</td><tr> <tr><td>null</td><td>2</td><tr> </table>

<table> <tr><td>student.coursescore.score</td><td>Repetition Level</td><tr> <tr><td>null</td><td>0</td><tr> <tr><td>null</td><td>2</td><tr> <tr><td>100</td><td>1</td><tr> </table>

基於Repetition level是能夠把原有的數據分好類,可是咱們如今咱們還不知道一條記錄到什麼位置STOP,以及數據以前的關係,這個時候在引入Definition Level。

這個時候在引入Definition Level 是定義的深度,用來記錄該列是不是虛擬出來的。因此對於非NULL的記錄,是沒有意義的,其值必然爲相同。一樣舉個例子。 好比對於master來講深度就是0,由於是required。

<table> <tr><td>master</td><td>Definition Level</td><tr> <tr><td>Jack</td><td>0</td><tr> <tr><td>BoBo</td><td>0</td><tr> </table>

<table> <tr><td>student.name</td><td>Definition Level</td><tr> <tr><td>tom</td><td>1</td><tr> <tr><td>joy</td><td>2</td><tr> <tr><td>null</td><td>1</td><tr> <table> 經過Definition Level能夠還原數據的嵌套關係。

其餘

parquet已經有hive,pig,spark,impala等數據處理框架的支持,同時也是spark建議parquet做爲其存儲格式。經過以上能夠看出,若是數據schema是扁平結構,那麼其實,repetition level 和 definition level 就徹底不須要。後續會繼續寫一些數據處理引擎的文檔。

相關文章
相關標籤/搜索