カラムナフォーマットParquetの構造とReadの最適化

logserializehadoop

Parquetは主にHadoopのエコシステムで使われるカラムナフォーマット。 CSVのようなrow-basedのフォーマットと比べて不必要なカラムを読まずに済み、また行に関しても絞るための仕組みがあるので効率的にクエリを実行することができる。

フォーマット

https://github.com/apache/parquet-format#file-format

行はいくつかのRow Groupに水平分割され、その中に各カラムのColumn Chunkが順に並んでいる。Column ChunkはさらにPageに分けられ、その単位で圧縮やエンコーディングが行われる。

一方向にファイルを書き込めるようにRowGroupの後にメタデータが来るようになっている。

ネストしたスキーマにも対応していて、フラットにした後にRepetiton LevelとDefinition Levelで繰り返しや階層を表している

Readの最適化

ColumnMetadataにレコード数や最小最大値、圧縮コーデックやサイズが含まれているため、Readerは必要なものだけを展開して読むことができる。 したがって取得するカラムを絞ったり、フィルタに用いるカラムをソートしておくと読むPageを減らすことができる。

メタデータの例

公式のCLIツールであるparquet-cliで実ファイルのメタデータを見てみる。 parquet-toolsというのもあるがすでにdeprecatedになっておりリポジトリからも消えている。

$ brew install parquet-cli

AWS Glueでjsonから変換したparquetを対象としている。

$ cat test.json
{"A":"aaaa","B":["b"],"C":{"D":10}}

$ parquet meta test.parquet

File path:  test.parquet
Created by: parquet-glue version 1.8.2
Properties:
  org.apache.spark.sql.parquet.row.metadata: {"type":"struct","fields":[{"name":"A","type":"string","nullable":true,"metadata":{}},{"name":"B","type":{"type":"array","elementType":"string","containsNull":true},"nullable":true,"metadata":{}},{"name":"C","type":{"type":"struct","fields":[{"name":"D","type":"integer","nullable":true,"metadata":{}}]},"nullable":true,"metadata":{}}]}
Schema:
message glue_schema {
  optional binary A (STRING);
  optional group B (LIST) {
    repeated group list {
      optional binary element (STRING);
    }
  }
  optional group C {
    optional int32 D;
  }
}


Row group 0:  count: 1  216.00 B records  start: 4  total: 216 B
--------------------------------------------------------------------------------
                type      encodings count     avg size   nulls   min / max
A               BINARY    G   _     1         76.00 B    0       "aaaa" / "aaaa"
B.list.element  BINARY    G   _     1         66.00 B    0       "b" / "b"
C.D             INT32     G   _     1         74.00 B    0       "10" / "10"

参考

What is Apache Parquet? - Databricks