This page looks best with JavaScript enabled

Parquet

 ·  ☕ 2 min read

Parquet

最近在工作上要把一堆 spark app 讀的檔案從 json 換成 parquet
就小小研究一下這東西到底是什麼
parquet 其實就是一種資料儲存的檔案格式,且是 binary encoding,人眼看不懂

像在之前我寫的這篇文章介紹,用純文字的方式去存 json 這種 key value 的 object,在 deserialize 的時候要花很大的力氣一個一個字元去讀,而且處存空間花費也很大,沒有做任何的壓縮

parquet 用在一個 row group 內用 column-oriented 的方式去存資料,還有多存了一些 metadata,在分析用途且資料量大的時候就會很有效率

parquet 檔案長相如下

Ref: https://parquet.apache.org/docs/file-format/

檔案內主要包含 data 和 footer file metadata 兩個部分。
一筆一筆的紀錄會被分散放在各個 row group 內,接著 group 內會有很多 column chunks,每個 chunk 都包著多筆紀錄的同一個欄位,切著被切分為 pages,每一個 page 基本上來說是不可分割的,是拿來壓縮和 encoding 的單位。


Ref: https://www.linkedin.com/pulse/all-you-need-know-parquet-file-structure-depth-rohan-karanjawala/

在可以看到 footer 中的 file metadata 包含了 row groups 和 column chunks 的位置,所以這些東西其實是可以分開存在不同地方。
把 metadata 寫在尾端的好處是可以 one pass 寫入

在讀資料的時候都是由 footer 開始,先找到需要讀的 column chunks 接著依序去讀
大量資料分析時通常都是讀所有資料的特定幾個 column 而已,column-oriented 資料編排方式可以跳過不需要的 column,如果是一般 row-oriented 的處存方式例如 Avro,就只能乖乖掃過所有資料
而因為同一個 column 都是同一種型態,同一個型態的資料都聚集在一起,所以在壓縮上也比 row-oriented 更容易
舉個簡單的例子,目前儲存了一個 enum 的 column 內容是 AAAAABBBB,那就可以把它壓縮成 5A4B 來儲存
DDIA 第三章有一個小節專門在講 column-oriented storage
之前如果有空再來寫一篇紀錄一下

Row group 與 data page size 都是可以調整的
Row group size 越大就可以讓 column chunks 更大,可以做更大的 sequential IO,不過在途中也會需要更多的 buffer。官方建議就是把一個 row group 剛好可以放進一個 HDFS block,1GB

data page size 的建議則是 8KB,越大的 size 可以減少 header 的數量與處理 header 的時間
小一點的 size 則是可以更有效率的 query 少量紀錄,因為在撈少量紀錄時不需要去處理很大的 page

Parquet 大概就看到這邊,總結就是它用 column-oriented 的方式去存資料,所以很適合資料分析,而且又存了很多 metadata 來讓各種操作減少很多 overhead (例如 index)

跟 Parquet 常常被一起提起的還有 ORC,ORC 似乎在某些方面表現稍微優於 parquet,不過 Parquet 在 Spark 上有做一些優化,而 ORC 則是適合跟 Hive 一起使用。但這部分就沒什麼研究了,之後有空再來看看好了。


Ref:
https://parquet.apache.org/docs/file-format/configurations/
https://www.linkedin.com/pulse/all-you-need-know-parquet-file-structure-depth-rohan-karanjawala/

Share on

Marko Peng
WRITTEN BY
Marko Peng
Good man