dev@parquet.apache.org で、parquet-mr の古いモジュールの廃止案が出ています。廃止対象の中には Parquet ファイルの情報を出力する Command Line Tool の parquet-tools も含まれています。
parquet-tools は Parquet ファイルの情報を確認するのに便利だったのですが、parquet-cli もあるので 2つ CLI をメンテするのはどうなんだろう?という話になっています。
私は parquet-cli は使ったことが無かったので、使い方を調べてみました。(2019/02/17 時点)
なお私が知る限りですが、「parquet-cli」という名前のツールは parquet-mr に含まれている Java のツールと、chhantyal/parquet-cli にある Python のツールの2種類があります。今回は parquet-mr の方を取り上げています。
使い方
parquet-cli を使いたい場合は、github から clone して parquet-mr のトップディレクトリで mvn install -DskipTests=true
で全モジュールを install するのが簡単です。Linux 環境でのビルドと実行方法は README.md にあります。
Command
parquet-cli は parquet-tools 同様、いくつかのコマンドが用意されています。
meta
Schema や Row Group 単位の情報を確認することができます。
$ java -cp target/classes;target/dependency/* org.apache.parquet.cli.Main meta C:\Users\masayuki\Downloads\test. parquet
File path: C:\Users\masayuki\Downloads\test.parquet
Created by: parquet-mr version 1.12.0-SNAPSHOT (build 1e62e2e2ca903d4109480bc87ceec1dc954b6c92)
Properties:
writer.model.name: example
Schema:
message test {
required int32 int32_field;
required int64 int64_field;
required float float_field;
required double double_field;
required binary binary_field;
required int64 timestamp_field (TIMESTAMP(MILLIS,true));
}
Row group 0: count: 395 15.87 B records start: 4 total: 6.120 kB
--------------------------------------------------------------------------------
type encodings count avg size nulls min / max
int32_field INT32 _ D 395 0.20 B 0 "32" / "426"
int64_field INT64 _ D 395 0.20 B 0 "64" / "458"
float_field FLOAT _ _ 395 4.13 B 0 "1.0" / "395.0"
double_field DOUBLE _ _ 395 8.13 B 0 "2.0" / "396.0"
binary_field BINARY _ D 395 2.98 B 0 "0x6162636465666768696A6B6..." / "0x6162636465666768696A6B6..."
timestamp_field INT64 _ D 395 0.23 B 0 "2018-11-04T12:41:15.123+0000" / "2018-11-04T12:47:49.123+0000"
Row group 1: count: 395 15.92 B records start: 6271 total: 6.142 kB
--------------------------------------------------------------------------------
type encodings count avg size nulls min / max
int32_field INT32 _ D 395 0.20 B 0 "427" / "821"
int64_field INT64 _ D 395 0.20 B 0 "459" / "853"
float_field FLOAT _ _ 395 4.13 B 0 "396.0" / "790.0"
double_field DOUBLE _ _ 395 8.13 B 0 "397.0" / "791.0"
binary_field BINARY _ D 395 3.03 B 0 "0x6162636465666768696A6B6..." / "0x6162636465666768696A6B6..."
timestamp_field INT64 _ D 395 0.23 B 0 "2018-11-04T12:47:50.123+0000" / "2018-11-04T12:54:24.123+0000"
Row group 2: count: 234 16.53 B records start: 12560 total: 3.777 kB
--------------------------------------------------------------------------------
type encodings count avg size nulls min / max
int32_field INT32 _ D 234 0.17 B 0 "822" / "1055"
int64_field INT64 _ D 234 0.31 B 0 "854" / "1087"
float_field FLOAT _ _ 234 4.11 B 0 "791.0" / "1024.0"
double_field DOUBLE _ _ 234 8.21 B 0 "792.0" / "1025.0"
binary_field BINARY _ D 234 3.38 B 0 "0x6162636465666768696A6B6..." / "0x6162636465666768696A6B6..."
timestamp_field INT64 _ D 234 0.35 B 0 "2018-11-04T12:54:25.123+0000" / "2018-11-04T12:58:18.123+0000"
count
はレコードの数です。min
と max
は Column Chunks の Statistics です。encodeings
の欄は2つあり、前者は Compression に関するもので、以下のようになっています。
1 public static String shortCodec(CompressionCodecName codec) {
2 switch (codec) {
3 case UNCOMPRESSED:
4 return "_";
5 case SNAPPY:
6 return "S";
7 case GZIP:
8 return "G";
9 case LZO:
10 return "L";
11 case BROTLI:
12 return "B";
13 case LZ4:
14 return "4";
15 case ZSTD:
16 return "Z";
17 default:
18 return "?";
19 }
20 }
後者は encoding に関するものです。この出力内容はフォーマットによって少し異なるようですが、概ね Delta 系が D
、Dictionary 系が R
、Plain が _
となります。
pages
Column Chunks の各ページの情報を出力します。
$ java -cp target/classes;target/dependency/* org.apache.parquet.cli.Main pages C:\Users\masayuki\Downloads\test.parquet
Column: int32_field
--------------------------------------------------------------------------------
page type enc count avg size size rows nulls min / max
0-0 data _ D 300 0.07 B 21 B 300 0
0-1 data _ D 95 0.12 B 11 B 95 0
1-0 data _ D 300 0.07 B 22 B 300 0
1-1 data _ D 95 0.12 B 11 B 95 0
2-0 data _ D 234 0.07 B 17 B 234 0
Column: int64_field
--------------------------------------------------------------------------------
page type enc count avg size size rows nulls min / max
0-0 data _ D 200 0.09 B 17 B 200 0
0-1 data _ D 195 0.09 B 17 B 195 0
1-0 data _ D 200 0.09 B 17 B 200 0
1-1 data _ D 195 0.09 B 17 B 195 0
2-0 data _ D 200 0.09 B 17 B 200 0
2-1 data _ D 34 0.32 B 11 B 34 0
Column: float_field
--------------------------------------------------------------------------------
page type enc count avg size size rows nulls min / max
0-0 data _ _ 300 4.00 B 1.172 kB 300 0
0-1 data _ _ 95 4.00 B 380 B 95 0
1-0 data _ _ 300 4.00 B 1.172 kB 300 0
1-1 data _ _ 95 4.00 B 380 B 95 0
2-0 data _ _ 234 4.00 B 936 B 234 0
Column: double_field
--------------------------------------------------------------------------------
page type enc count avg size size rows nulls min / max
0-0 data _ _ 200 8.00 B 1.563 kB 200 0
0-1 data _ _ 195 8.00 B 1.523 kB 195 0
1-0 data _ _ 200 8.00 B 1.563 kB 200 0
1-1 data _ _ 195 8.00 B 1.523 kB 195 0
2-0 data _ _ 200 8.00 B 1.563 kB 200 0
2-1 data _ _ 34 8.00 B 272 B 34 0
Column: binary_field
--------------------------------------------------------------------------------
page type enc count avg size size rows nulls min / max
0-0 data _ D 100 2.75 B 275 B 100 0
0-1 data _ D 100 2.77 B 277 B 100 0
0-2 data _ D 100 2.77 B 277 B 100 0
0-3 data _ D 95 2.61 B 248 B 95 0
1-0 data _ D 100 2.83 B 283 B 100 0
1-1 data _ D 100 2.83 B 283 B 100 0
1-2 data _ D 100 2.83 B 283 B 100 0
1-3 data _ D 95 2.62 B 249 B 95 0
2-0 data _ D 100 2.82 B 282 B 100 0
2-1 data _ D 100 2.82 B 282 B 100 0
2-2 data _ D 34 4.56 B 155 B 34 0
Column: timestamp_field
--------------------------------------------------------------------------------
page type enc count avg size size rows nulls min / max
0-0 data _ D 200 0.12 B 23 B 200 0
0-1 data _ D 195 0.12 B 23 B 195 0
1-0 data _ D 200 0.12 B 23 B 200 0
1-1 data _ D 195 0.12 B 23 B 195 0
2-0 data _ D 200 0.12 B 23 B 200 0
2-1 data _ D 34 0.47 B 16 B 34 0
page
はページのインデックスで、「(Row Group Index)-(Page Index)」のフォーマットで出力します。type
は Data ページの場合は data
、Dictionary ページの場合は dict
と表示されます。min
と max
が表示されていないのは、前回書いた ColumnIndex の対応で、ページには Statistics を書き込まないようになっている為です。
dictionary
指定した column の dictionary データを表示します。指定した column が dictionary encoding になっている必要があります。
$ java -cp 'target/classes:target/dependency/*' org.apache.parquet.cli.Main dictionary /work/parquet-mr/data/userdata1.parquet -c last_name
Row group 0 dictionary for "last_name":
0: "Jordan"
1: "Freeman"
2: "Morgan"
3: "Riley"
4: "Burns"
5: "White"
6: "Holmes"
7: "Howell"
8: "Foster"
9: "Stewart"
10: "Perkins"
...
check-stats
これは help コマンドで出力される以下の説明にあるように、PARQUET-251 で対応されている Statistics の不具合を確認するコマンドです。大分前の Issue なので、最近作成した Parquet ファイルに対して使うことは無いと思います。
check-stats
Check Parquet files for corrupt page and column stats (PARQUET-251)
schema
Parquet ファイルの Schema を表示します。Avro の Schema も表示できます。
$ java -cp 'target/classes:target/dependency/*' org.apache.parquet.cli.Main schema /work/parquet-mr/data/test.parquet
{
"type" : "record",
"name" : "test",
"fields" : [ {
"name" : "int32_field",
"type" : "int"
}, {
"name" : "int64_field",
"type" : "long"
}, {
"name" : "float_field",
"type" : "float"
}, {
"name" : "double_field",
"type" : "double"
}, {
"name" : "binary_field",
"type" : "bytes"
}, {
"name" : "timestamp_field",
"type" : {
"type" : "long",
"logicalType" : "timestamp-millis"
}
} ]
}
csv-schema
CSV ファイルのデータを読んで Schema を表示します。以下のような CSV ファイルを用意して、
emp_id,dept_id,name,created_at,updated_at
1,1,"test1","2019-02-17 10:00:00","2019-02-17 12:00:00"
2,2,"test2","2019-02-17 10:00:00","2019-02-17 12:00:00"
以下のように実行すると、Schema が出力されます。
$ java -cp 'target/classes:target/dependency/*' org.apache.parquet.cli.Main csv-schema /work/parquet-mr/data/test.csv --record-name Test
{
"type" : "record",
"name" : "Test",
"fields" : [ {
"name" : "emp_id",
"type" : [ "null", "long" ],
"doc" : "Type inferred from '1'",
"default" : null
}, {
"name" : "dept_id",
"type" : [ "null", "long" ],
"doc" : "Type inferred from '1'",
"default" : null
}, {
"name" : "name",
"type" : [ "null", "string" ],
"doc" : "Type inferred from 'test1'",
"default" : null
}, {
"name" : "created_at",
"type" : [ "null", "string" ],
"doc" : "Type inferred from '2019-02-17 10:00:00'",
"default" : null
}, {
"name" : "updated_at",
"type" : [ "null", "string" ],
"doc" : "Type inferred from '2019-02-17 12:00:00\" '",
"default" : null
} ]
}
convert-csv
CSV ファイルを Parquet フォーマットのファイルに変換します。
$ java -cp 'target/classes:target/dependency/*' org.apache.parquet.cli.Main convert-csv ../data/test.csv -o ../data/test-csv.parquet
$ java -cp 'target/classes:target/dependency/*' org.apache.parquet.cli.Main head -n 10 ../data/test-csv.parquet
{"emp_id": 1, "dept_id": 1, "name": "test1", "created_at": "2019-02-17 10:00:00", "updated_at": "2019-02-17 12:00:00\" "}
{"emp_id": 2, "dept_id": 2, "name": "test2", "created_at": "2019-02-17 10:00:00", "updated_at": "2019-02-17 12:00:00"}
convert
Avro フォーマットのファイルを Parquet フォーマットのファイルに変換します。
java -cp 'target/classes:target/dependency/*' org.apache.t.cli.Main convert /work/parquet-mr/data/userdata1.avro -o ../data/userdata1.parquet
to-avro
convert
の逆で、Parquet フォーマットのファイルを Avro フォーマットのファイルに変換します。
java -cp 'target/classes:target/dependency/*' org.apache.parquet.cli.Main to-avro /work/parquet-mr/data/test.parquet -o ../data/test.avro
head
cat
と head
は Parquet ファイル内のデータを出力するコマンドです。どちらのコマンドも、先頭から -n
で指定した分だけレコードを出力します。cat
は -n
を指定しないと全データを出力します。
java -cp 'target/classes:target/dependency/*' org.apache.parquet.cli.Main head -n 5 /work/parquet-mr/data/test.parquet
{"int32_field": 32, "int64_field": 64, "float_field": 1.0, "double_field": 2.0, "binary_field": {"bytes": "abcdefghijklmnopqrstuvwxyz0"}, "timestamp_field": 1541335275123}
{"int32_field": 33, "int64_field": 65, "float_field": 2.0, "double_field": 3.0, "binary_field": {"bytes": "abcdefghijklmnopqrstuvwxyz1"}, "timestamp_field": 1541335276123}
{"int32_field": 34, "int64_field": 66, "float_field": 3.0, "double_field": 4.0, "binary_field": {"bytes": "abcdefghijklmnopqrstuvwxyz2"}, "timestamp_field": 1541335277123}
{"int32_field": 35, "int64_field": 67, "float_field": 4.0, "double_field": 5.0, "binary_field": {"bytes": "abcdefghijklmnopqrstuvwxyz3"}, "timestamp_field": 1541335278123}
{"int32_field": 36, "int64_field": 68, "float_field": 5.0, "double_field": 6.0, "binary_field": {"bytes": "abcdefghijklmnopqrstuvwxyz4"}, "timestamp_field": 1541335279123}
column-index
ColumnIndex を出力します。
$ java -cp 'target/classes:target/dependency/*' org.apache.parquet.cli.Main column-index ../data/test.parquet
row-group 0:
column index for column int32_field:
Boudary order: ASCENDING
null count min max
page-0 0 32 331
page-1 0 332 426
offset index for column int32_field:
offset compressed size first row index
page-0 4 44 0
page-1 48 34 300
...
Conclusion
parquet-tools と比較すると、ファイルの内容を表示する機能は大体同じですが、CSV や Avro から Parquet に変換する機能が付いているのが嬉しいところです。