🅿️

Parquet の data encoding のサポート状況(2025年2月時点)

2025/02/05に公開

DuckDB が「DuckDB の新しいバージョンでは Parquet の新しめの encoding で書き出せるようになるけど、それを読めない奴らのせいでデフォルト有効にできないっすわ💢」というお気持ち表明ブログを書いていました。ここで「encoding」というのは、文字コードとかの話ではなくて、データをより少ないバイト数で記述する方法のことです。例えば、RLE(連長圧縮)のようなものです。

https://duckdb.org/2025/01/22/parquet-encodings.html

私はこれを読むまで Parquet の encoding の種類についてよく知らなかったので、勉強もかねてよく使われるツールの実装状況を調べてまとめてみます。

追記:公式に「Implementation status」というページがありました。書かれていないものも多いですが、ある程度は役立ちそうです。

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

新しめの data encoding

まずは Parquet の仕様を読みましょう。

https://parquet.apache.org/docs/file-format/data-pages/encodings/

このページによれば、非推奨の GROUP_VAR_INT[1]BIT_PACKED を除くと、以下の encoding が仕様として定義されています。

  • Plain (PLAIN)
  • Dictionary Encoding (PLAIN_DICTIONARYRLE_DICTIONARY)
  • Run Length Encoding (RLE)
  • Delta Encoding (DELTA_BINARY_PACKED): RLE をより効率的にした感じのやつ。整数向け。
  • Delta-length Byte Array (DELTA_LENGTH_BYTE_ARRAY): バイナリデータを詰めてくっつけてオフセットと長さを別で持っておくやつ。文字列やバイナリデータ向け。
  • Delta Strings (DELTA_BYTE_ARRAY): バイナリデータ版の delta encoding みたいなやつ。
  • Byte Stream Split (BYTE_STREAM_SPLIT): 実数向け。これは他のと違ってサイズは変わらないけど、この encoding をかけておくことで圧縮が効きやすくなるらしい。

DuckDB のブログによれば、BYTE_STREAM_SPLITは2019年から、それ以外も2015年にはすでに存在していた機能です。ということで、定義としてはまあまあ前からあるみたいです。

we're excited to have implemented the DELTA_BINARY_PACKED, DELTA_LENGTH_BYTE_ARRAY (added in Parquet 2.2.0 in 2015), and BYTE_STREAM_SPLIT (added in Parquet 2.8.0 in 2019) encodings in our Parquet writer.

DuckDB

DuckDB は、write に関しては次のバージョン(v1.2)からですが、read は少し前から実装されていました。

RLEDELTA_BINARY_PACKEDDELTA_BYTE_ARRAYDELTA_LENGTH_BYTE_ARRAYについては 2022年(v0.7.0)から、

https://github.com/duckdb/duckdb/pull/5457

BYTE_STREAM_SPLIT についても 2023年(v0.9.1)からサポートされていました。

https://github.com/duckdb/duckdb/pull/9240

Apache Arrow

2020年からサポートしてるみたいです。さすがは Apache project なだけあって早い。

https://github.com/apache/arrow/pull/6005

ただ、BYTE_STREAM_SPLIT は Parquet v2.8 で入ったものですが、Apache Arrow はそれを読み書きできるけどサポートしてるバージョンは v2.6 まで、ということになってるみたいです。謎...(実質なにか問題があるわけではなさそうな気はします)

https://github.com/apache/arrow/issues/35776

https://github.com/apache/arrow/blob/2cbc7d696cef76b61391064b0395b15edcc246a3/cpp/src/parquet/type_fwd.h#L63-L67

Apache Spark

Spark では、read は DELTA_BINARY_PACKEDDELTA_BYTE_ARRAYDELTA_LENGTH_BYTE_ARRAY は 2022年(v3.3.0 )からサポートされています。BYTE_STREAM_SPLIT に関しては今もサポートしていないようです。

https://issues.apache.org/jira/browse/SPARK-36879

https://spark.apache.org/releases/spark-release-3-3-0.html#built-in-connector-enhancements

write に関してはいずれもサポートされていません。そもそもチケットすら見つからないので、Spark は対応遅めなのかもですね...

Python

※あまり詳しくないです

pyarrow

(Apache Arrow と同じはず)

Pandas

Pandas が Parquet を読むときは、pyarrow があればそっちを、なければ fastparquet を使うようになっているはずです。pyarrow はまあ Arrow なので問題なく読み書きできるとして、fastparquet はというと、どうやら実装されているのは DELTA_BINARY_PACKED の read までのようです。

https://github.com/dask/fastparquet/blob/95416ad4214a21805c8256e5308272bec60cc177/fastparquet/core.py#L227-L233

Polars

Polars は 2024年(v1.0)で BYTE_STREAM_SPLIT まで対応できています。読み書きどっちもだと思います。

https://github.com/pola-rs/polars/commit/4731834e4b9737f862c081c3a492a2e5399c0e55

R

arrow

(Apache Arrow と同じはず)

nanoparquet

nanoparquet 自体が去年 CRAN リリースされたばかりのもの[2]ですが、v0.3 の時点で BYTE_STREAM_SPLIT の read までは対応しています。write は、RLE_DICTIONARY v0.4 で使えるようになりましたが、それ以上の計画があるのかは不明です。

https://nanoparquet.r-lib.org/news/index.html#nanoparquet-030

Trino

BYTE_STREAM_SPLIT は2024年(v444)でサポートされていました。他はリリースノートに記述をみつけられなかったので、けっこう前からサポートされているんだと思います。

https://trino.io/docs/current/release/release-444.html

Presto

BYTE_STREAM_SPLIT でコードを検索しても何も出ないので、対応してなさそうです。

https://github.com/search?q=repo%3Aprestodb%2Fpresto BYTE_STREAM_SPLIT &type=code

Hive

Hive は、Parquet 公式の Java 実装を使っていて、割と新しめなので普通に読めそうです。

以下の pull request を見て「まだバージョン 1.x なの...?」と思ってたら、これは Parquet フォーマットのバージョンではなく Java 実装のバージョンでした。

https://github.com/apache/hive/pull/5552

Tableau

DELTA_LENGTH_BYTE_ARRAY エンコードと最近の BYTE_STREAM_SPLIT エンコードは、どのライブラリでも記述されていないため、サポートされていません。これらのエンコーディングを使用している Parquet ファイルを見つけた場合は、お知らせください。
(https://help.tableau.com/current/pro/desktop/ja-jp/examples_amazons3.htm)

とのことです...。

脚注
  1. GROUP_VAR_INT はもう定義書には書かれてなくて、Thrift のコードでもコメントアウトされています。 ↩︎

  2. miniparquet というパッケージを r-lib チームがフォークしてCRAN リリースしたのが 2024 年。miniparquet 自体はもっと前からある。 ↩︎

Discussion