為什麼我們選擇parquet做數據存儲格式
- 2019 年 10 月 4 日
- 筆記
來源:https://www.cnblogs.com/piaolingzxh/p/5469964.html
作者:zhangxuhui
By 暴走大數據
場景描述:Parquet 是列式存儲的一種文件類型。
關鍵詞:Parquet 數據存儲
聲明:本文作者zhangxuhui,版權歸其個人所有。
場景描述
我們對客戶登錄日誌做了數據倉庫,但實際業務使用中有一些個共同點,
A 需要關聯維度表
B 最終僅取某個產品一段時間內的數據
C 只關注其中極少的欄位
基於以上業務,我們決定每天定時統一關聯維度表,對關聯後的數據進行另外存儲。各個業務直接使用關聯後的數據進行離線計算。
選擇parquet的外部因素
在各種列存儲中,我們最終選擇parquet的原因有許多。除了parquet自身的優點,還有以下因素
A、公司當時已經上線spark 集群,而spark天然支援parquet,並為其推薦的存儲格式(默認存儲為parquet)。
B、hive 支援parquet格式存儲,如果以後使用hiveql 進行查詢,也完全兼容。
選擇parquet的內在因素
下面通過對比parquet和csv,說說parquet自身都有哪些優勢
csv在hdfs上存儲的大小與實際文件大小一樣。若考慮副本,則為實際文件大小*副本數目。(若沒有壓縮)
parquet採用不同壓縮方式的壓縮比

說明:原始日誌大小為214G左右,120+欄位
採用csv(非壓縮模式)幾乎沒有壓縮。
採用parquet 非壓縮模式、gzip、snappy格式壓縮後分別為17.4G、8.0G、11G,達到的壓縮比分別是:12、27、19。
若我們在hdfs上存儲3份,壓縮比仍達到4、9、6倍
分區過濾與列修剪
分區過濾
parquet結合spark,可以完美的實現支援分區過濾。如,需要某個產品某段時間的數據,則hdfs只取這個文件夾。
spark sql、rdd 等的filter、where關鍵字均能達到分區過濾的效果。
使用spark的partitionBy 可以實現分區,若傳入多個參數,則創建多級分區。第一個欄位作為一級分區,第二個欄位作為2級分區。
列修剪
列修剪:其實說簡單點就是我們要取回的那些列的數據。
當取得列越少,速度越快。當取所有列的數據時,比如我們的120列數據,這時效率將極低。同時,也就失去了使用parquet的意義。
分區過濾與列修剪測試如下:

說明:
A、task數、input值、耗時均為spark web ui上的真實數據。
B、之所以沒有驗證csv進行對比,是因為當200多G,每條記錄為120欄位時,csv讀取一個欄位算個count就直接lost excuter了。
C、注意:為避免自動優化,我們直接列印了每條記錄每個欄位的值。(以上耗時估計有多部分是耗在這裡了)
D、通過上圖對比可以發現:
- 當我們取出所有記錄時,三種壓縮方式耗時差別不大。耗時大概7分鐘。
- 當我們僅取出某一天時,parquet的分區過濾優勢便顯示出來。僅為6分之一左右。貌似當時全量為七八天左右吧。
- 當我們僅取某一天的一個欄位時,時間將再次縮短。這時,硬碟將只掃描該列所在rowgroup的柱面。大大節省IO。

E、測試時請開啟filterpushdown功能
結論
parquet的gzip的壓縮比率最高,若不考慮備份可以達到27倍。可能這也是spar parquet默認採用gzip壓縮的原因吧。
分區過濾和列修剪可以幫助我們大幅節省磁碟IO。以減輕對伺服器的壓力。
如果你的數據欄位非常多,但實際應用中,每個業務僅讀取其中少量欄位,parquet將是一個非常好的選擇。