That's Done!

thatsdone's (mostly technical) memorandum

[ja] JSONをParquestに保存するのにApache Arrowを使ってみる


事情で表記のようなことを考える必要があり、Parquetをちょっと調べています。

とりあえず、使いたい言語がPythonだったこと、Pandas等とも連携できることを考えて、Apache ArrowのPython bindingを使ってみることにしました。

参考情報

インストール

大人の事情でCentOS7系で動作確認したかったので、Pythonは(未だに)2.7系を使っています(苦笑)

Apache Arrow自体は新しいものを使いたかったので、virtualenv を使って以下のようにお手軽に作成しました。

$ virtualenv venvs/arrow
$ source venvs/arrow/bin/activate
$ pip install pyarrow

とりあえずやってみたこと

以下のようなテストデータを作って

{
    "key1": 1,
    "key2": "value2-1",
     "key3": ["value3-1", "value3-1"]
}

以下のようなプログラムで試しました。

import pyarrow.parquet as pq
from pyarrow import json as pajson

table = pajson.read_json('test.json')

print('==================write table')
pq.write_table(table, 'test.parquet')

print('==================using parquet.read_schema')
schema = pq.read_schema('test.parquet')
print(schema)

実行するとこんな感じになります。

$ python test.py
==================write table
==================using parquet.read_schema
key1: int64
key2: string
key3: list<item: string>
  child 0, item: string
metadata
--------
OrderedDict([('ARROW:schema', '/////wgBAAAQAAAAAAAKAAwABgAFAAgACgAAAAABAwAMAAAACAAIAAAABAAIAAAABAAAAAMAAACcAAAAXAAAAAQAAACA////AAABDEAAAAAQAAAABAAAAAEAAAAIAAAAsP///6D///8AAAEFFAAAAAwAAAAEAAAAAAAAAMz///8EAAAAaXRlbQAAAAAEAAAAa2V5MwAAAADU////AAABBRgAAAAQAAAABAAAAAAAAAAEAAQABAAAAAQAAABrZXkyAAAAABAAFAAIAAYABwAMAAAAEAAQAAAAAAABAiQAAAAUAAAABAAAAAAAAAAIAAwACAAHAAgAAAAAAAABQAAAAAQAAABrZXkxAAAAAAAAAAA=')])

後述の通り、先にスキーマを作らなくても動くのかどうか確認したかったのですが、入力に従ったスキーマが作成されているようです。

余談ですが、1レコードしかないので、サイズはこんな感じになりますね(苦笑)

$ du -b test.json test.parquet
80      test.json
232 test.parquet

TODO

  • 圧縮を試す
  • 複数レコード格納する
    • 後述のトップレベル名無し配列の件も調べる
  • 事前にスキーマを定義した場合と動的に作成させた場合の違いの確認
  • スキーマにないelementが現れた場合の挙動の確認

TIPS(というか気づいたことのメモ)

スキーマは事前に準備しなくても動く

確かに動くのですが、これで最適なのか、確認要。(TBD)

pyarrow.json では Objectのネストはできない

以下の例では "key4"の値はさらにObject(Pythonではdcit)になっていますが、これはpyarrow.json.read_json()に食わせるとエラーになるようです。

{
  "key1": 1,
  "key2": "value2-1",
  "key3": [
    "value3-1",
    "value3-1"
  ],
  "key4": {
    "key41": 4,
    "key42": "value42"
  }
}

JSONで許されているトップレベルの名無しArrayは通らない

JSONの規格上、以下のようなデータは許されているのですが、

[
  {
    "key1": 1,
    "key2": "value2-1",
    "key3": [
      "value3-1",
      "value3-1"
      ] 
  },
  {
    "key1": 2,
    "key2": "value2-2",
    "key3": [
      "value3-2",
      "value3-2"
    ]
  }
]

しかし、こんな感じでエラーになります。 これは、Arrayの要素を1つに減らしても同じです。

$ python test.py
Traceback (most recent call last):
  File "test.py", line 6, in <module>
    table = pajson.read_json('test3.json')
  File "pyarrow/_json.pyx", line 193, in pyarrow._json.read_json
  File "pyarrow/error.pxi", line 84, in pyarrow.lib.check_status
pyarrow.lib.ArrowInvalid: JSON parse error: Column() changed from object to array in row 0

続きます。