25
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Google Cloud Platform(1)Advent Calendar 2016

Day 6

BigqueryのAVROフォーマットエクスポートをembulk-parser-avroで活用する

Last updated at Posted at 2016-12-06

Bigqueryはしばらく前から、AVROフォーマットでデータをエクスポートできるようになっています。
AVROフォーマットは、Apacheプロジェクトの一つとして開発されているシリアライズフォーマットで、以下の様な特徴を持ちます。

  • バイナリフォーマットでとてもコンパクト
  • 型情報を持ったスキーマがある、スキーマはJSONで定義する
  • JSONの様に入れ子が可能
  • null可かどうかをスキーマで表現可能
  • シリアライズして出力した後でも別のスキーマに変更できる

恐らく一番大きな特徴は型付きでバイナリにシリアライズしているのに、後からカラムを追加したり削除して読み出すことができる点です。
スキーマ情報はファイル内に埋め込まれていますが、別途定義したものと組み合わせて読み出すことができ、後からデフォルト値を追加したりできるようになっています。
また、Hadoopから直接データを読み出せるライブラリが揃っていて、Hadoopエコシステムと相性が良いという性質もあります。
JSONと比べた時の利点は、型がよりかっちり決まっている点と、バイナリフォーマットで末尾まで読まなくても随時パースしながらストリームで処理できる点です。
まあ、Bigqueryの場合はエクスポートの出力がlined JSONなので、その辺りはあんまり変わらないですが、パースの負荷は軽くて済みます。

さて、AVROはBigqueryのデータエクスポートには、JSONとAVROで大きな違いがあります。
BigqueryはJSONでエクスポートすると何でもかんでも文字列になって出力されます intとtimestampが文字列になって出力されます。
JSONだとこれが割と面倒で、そこそこのデータ量を取得して別の用途に利用しようとすると、無駄な型変換が必要になって処理負荷がかかります。
特に面倒なのが、ARRAY型をエクスポートした時で配列内部にあるデータも文字列になっているので、数値の配列が欲しい場合は一回全データを走査して数値に変換する必要があります。

AVROだとその辺りは、大体一致した型で出力されます。(時刻はlong型になります)
配列内部のデータもちゃんとイメージ通りの型で出力してくれるので、余計な変換をする手間が省けます。

私はBigqueryから出力したデータはembulkを利用して取得・加工を行うことが多いので、embulkからAVROフォーマットを扱えるようにembulk-parser-avroを作りました

in:
 type: file
 path_prefix: "items"
 parser:
   type: avro
   avsc : "./item.avsc"
   columns:
     - {name: "id", type: "long"}
     - {name: "code", type: "string"}
     - {name: "name", type: "string"}
     - {name: "description", type: "string"}
     - {name: "flag", type: "boolean"}
     - {name: "price", type: "long"}
     - {name: "item_type", type: "string"}
     - {name: "tags", type: "json"}
     - {name: "options", type: "json"}
     - {name: "spec", type: "json"}
     - {name: "created_at", type: "timestamp", format: "%Y-%m-%dT%H:%M:%S%:z"}
     - {name: "created_at_utc", type: "timestamp"}

out:
 type: stdout
// item.avsc

{
 "type" : "record",
 "name" : "Item",
 "namespace" : "example.avro",
 "fields" : [
   {"name": "id", "type": "int"},
   {"name": "code", "type": "long"},
   {"name": "name", "type": "string"},
   {"name": "description", "type": ["string", "null"]},
   {"name": "flag", "type": "boolean"},
   {"name": "created_at", "type": "string"},
   {"name": "created_at_utc", "type": "float"},
   {"name": "price", "type": ["double", "null"]},
   {"name": "spec", "type": {
     "type": "record",
     "name": "item_spec",
     "fields" : [
       {"name" : "key", "type" : "string"},
       {"name" : "value", "type" : ["string", "null"]}
     ]}
   },
   {"name": "tags", "type": [{"type": "array", "items": "string"}, "null"]},
   {"name": "options", "type": {"type": "map", "values": ["string", "null"]}},
   {"name": "item_type", "type": {"name": "item_type_enum", "type": "enum", "symbols": ["D", "M"]}},
   {"name": "dummy", "type": "null"}
 ]
}

こんな感じで利用できます。
Bigqueryからデータを出力した後で、それを加工する際の型変換が無駄だなーと思ってる方が居たら、使ってみてはどうでしょうか。
~

25
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
25
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?