這篇文章將為大家詳細講解有關大數(shù)據(jù)存儲格式parquet是怎樣的,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。
成都創(chuàng)新互聯(lián)公司長期為近千家客戶提供的網(wǎng)站建設服務,團隊從業(yè)經(jīng)驗10年,關注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務;打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為蘭西企業(yè)提供專業(yè)的網(wǎng)站建設、成都做網(wǎng)站,蘭西網(wǎng)站改版等技術服務。擁有十年豐富建站經(jīng)驗和眾多成功案例,為您定制開發(fā)。
首先我們從關系數(shù)據(jù)庫入手,來看關系數(shù)據(jù)庫的一些常見查詢。對于關系數(shù)據(jù)庫而言,我們常見的查詢一般有詳情查詢或者統(tǒng)計分組,但是如果是大數(shù)據(jù)量的情況下,關系數(shù)據(jù)庫是不能很好的支持統(tǒng)計類的查詢,所以一般關系數(shù)據(jù)庫多有于對OLTP業(yè)務,那么常見的大數(shù)據(jù)的查詢有個特點,由于數(shù)據(jù)量很大,獲取具體的詳情數(shù)據(jù)意義不大,所以基本都是統(tǒng)計類的查詢,如:select count(1) cnt,ip from access_log group by ip,查詢每個ip的訪問次數(shù)。當然也可能有查詢詳細做深度的數(shù)據(jù)分析。
對于查詢速度當然是越快越好,我們可以從以下幾個方面來提高這個系統(tǒng)的查詢速度(當然緩存不在考慮的范疇內(nèi)),1.查詢系統(tǒng)框架的優(yōu)化,這里可能包含了(執(zhí)行計劃啊,分布式計算等等等),2.底層文件存儲格式的優(yōu)化,盡量減少IO.3.當然還有索引技術.
針對上面的sql:select count(1) cnt,ip from access_log group by ip
我們假設access_log的格式如下: access_log{ string ip; string access_time; ............(其他N個屬性)
}
如果是行存儲:
我們需要讀取一行的所有數(shù)據(jù),然后獲取其中的ip字段,在做分組統(tǒng)計。增加的磁盤的IO,同時也增加了計算壓力.
如果是列存儲會如何:
對于上面的統(tǒng)計,我們只需要讀取IP就可以,讀取不需要的列信息,這就是列存儲對于大數(shù)據(jù)的統(tǒng)計類查詢的優(yōu)點所在,當然除此之外大數(shù)據(jù)本身的稀疏性,采用列式可能更好的去優(yōu)化存儲結(jié)構(gòu),減少存儲空間.
parquet是twitter在2013年開源的數(shù)據(jù)結(jié)構(gòu),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").這個大數(shù)據(jù)查詢利器的paper里面,其實主要也是在闡述底層文件存儲格式。
Parquet支持復雜嵌套的數(shù)據(jù)結(jié)構(gòu)組成,并使用重復級別/定義級別(repetition/definition level )的方法來對數(shù)據(jù)結(jié)構(gòu)進行編碼,嵌套的方式其實可以避免了大數(shù)據(jù)的join問題.
Parquet支持對某一列數(shù)據(jù)進行壓縮,支持任意開發(fā)語言的讀寫操作.目前是apache的頂級項目.
首先來看一下如何定義一個parquet的文件格式,這里也是采用類似PB的格式定義 這里采用了班級信息來作為示例,有多個班級,每一個班級有個master,有多個學生(可以無),每個學生有名稱和多個愛好,還有每一門可課程的成績以及課程名稱. schema定義: message classroom{ required string master; repeated group students{ required string name; repeated string hobbys; repeated group coursescore{ required string name; optional string score; } } }
required 表示必填 repeated 表示可以有任意個 optional 0 or 1 對于數(shù)據(jù)可以關系可以分為Map以及List,如果為List可以采用repeated,Map采用group 關鍵字修飾.
這里我們來定義一組數(shù)據(jù):
{ master:"jack", student: name:"tom" student: name:"joy", hobbys:"basketball", hobbys:"football", coursescore: name:"math", coursescore: name:"chinese", score:100 } { master:"BoBo" }
兩個班級一個有學生一個沒有,一個學生有愛好有課程,一個什么也沒有. 我們先來看看如何存儲.
依據(jù)上面定義的schema,可以先轉(zhuǎn)化為一個tree表示結(jié)構(gòu)
只有樹的根節(jié)點是需要實際存儲的數(shù)據(jù)節(jié)點,其余的只是關系的一種維系。 下圖展示了其嵌套關系
實際存儲也是這樣,每一列存儲了所有的數(shù)據(jù)信息。是不是存儲很容易。
既然所有的同一類的數(shù)據(jù)存儲在一起,那么數(shù)據(jù)如何還原為原來的數(shù)據(jù)。這里引入了parquet的元數(shù)據(jù)信息,如何還原數(shù)據(jù)需要 Repetition Level以及Definition Level這兩個元數(shù)據(jù)信息。
首先我們需要知道哪些數(shù)據(jù)是一組的,其實還需要知道數(shù)據(jù)和數(shù)據(jù)之間的層級關系,OK。這兩個元數(shù)據(jù)信息可以幫我們搞的.(當然也是存儲的時候?qū)懭氲脑獢?shù)據(jù)信息)
Repetition Level是記錄該列的值是在哪一個級別上重復的。
用剛才的兩個classroom信息來舉例: 對于兩個classroom的master來說,由于都是獨立的沒有直接關系,所以他們的Repetition level是0
Jack 0
BoBO 0
對于jack的學生tom,joy來說,tom是第一個學生,所以level是0,而joy平級,所以是1.
master | Repetition Level |
Jack | 0 |
BoBo | 0 |
student.name | Repetition Level |
tom | 0 |
joy | 1 |
null | 2 |
student.coursescore.score | Repetition Level |
null | 0 |
null | 2 |
100 | 1 |
基于Repetition level是可以把原有的數(shù)據(jù)分好類,但是我們現(xiàn)在我們還不知道一條記錄到什么位置STOP,以及數(shù)據(jù)之前的關系,這個時候在引入Definition Level。
這個時候在引入Definition Level 是定義的深度,用來記錄該列是否是虛擬出來的。所以對于非NULL的記錄,是沒有意義的,其值必然為相同。同樣舉個例子。 比如對于master來說深度就是0,因為是required。
master | Definition Level |
Jack | 0 |
BoBo | 0 |
student.name | Definition Level |
tom | 1 |
joy | 2 |
null | 1 |