為什麼我們選擇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將是一個非常好的選擇。