GoogleBigQueryを試してみた

ログの解析はユーザの動向や、ゲームであれば売上の良かったイベントなどを分析するためには欠かせないものであり、きっとどこの会社(や個人)でも、頭を悩ませたり力を入れていたりすると思います。

弊社でも数年前に大きな解析基盤を用意し現在でも利用しているのですが、月日が流れるに伴い、ログが大量になりすぎてスムーズな運用が厳しくなってきている現状があります。
構成としては簡単に言うとHadoopを使っており、flumeで転送、Hiveで取得という感じです。

古いデータも大切なモノなので削除していくということもできず、しかし思い通りに解析ができない!
せめて数ヶ月単位でもスムーズにできないものか…という意見から、だったら直近のデータ解析はBigQuery使ってみたらどうだろうか?

ということで、基本的な使い方から運用の方法まで考えてみました。

GoogleBigQiueryとは

カラム型データストアツリーアーキテクチャ
この2つが大きな特徴となっております。

カラム型データストア

行ではなく、列でまとめて格納する仕組みです。

ツリーアーキテクチャ

トップにあるクエリを受け取るサーバ(root server)から、処理担当のサーバ(leaf server)へ流れていきます。
このツリーアーキテクチャに使わているHDDは数千台だそうです。すごいですね。

hadoop - Googleの虎の子「BigQuery」をFluentdユーザーが使わない理由がなくなった理由 #gcpja - Qiita

構造についてはもちろんお魚の本にも詳細がありますが、
www.amazon.co.jp

こちらがとてもわかりやすいかと思います。

グーグルのBigQuery、高速処理の仕組みは「カラム型データストア」と「ツリー構造」。解説文書が公開 - Publickey

料金

サービス ストレージ ネットワーク帯域 クエリ
BigQuery 250円 / 100GB 60円 / 100GB
CloudStorage 300円 / 100GB 1000円 / 100GB

BigQueryはGCS(Google Cloud Storage)との併用が推奨されているので載せてみました。

使ってみよう!

お試しなら無料でできます。
BigQueryに限らず、GCPはDeveloper Consoleが使いやすくていいと思います。
BigQueryにはpublicdataというサンプルが用意されています。
例えば、その中のgithub_timelineには6,219,749列、3.54GBの大きさのテーブルがあります。
そこに
SELECT repository_url FROM [publicdata:samples.github_timeline] limit 1000

このクエリを投げてみると、1秒で返ってきました。
桁を増やしてリミットを1万件にしてみましたが、それでも1.6秒です。早いですね〜
10万件だと6.8秒でした。全然許容範囲ではないでしょうか。
ちなみに、

SELECT * FROM [publicdata:samples.github_timeline] limit 1000

列を指定しないと1000件でも2秒以上かかってしまうので、できるだけ列は指定する方がいいです。
列指向型なので、列単位の検索は得意ということですね。

MongoDBでシェル操作時に忘れがちなコマンド

仕事柄、日頃触れるDBがコロコロと変わるので、久しぶりにMongoDBに戻ってくるたびに 「あれ、あれどうやるんだっけ!?」となるので備忘録。

全件取得

db.hoge.find()

出力結果

> db.user.find()
{ "_id" : ObjectId("15cdcc0e14e2a44b82d2e3d6"), "user_id": "user001", "name": "A", "age": 11},
{ "_id" : ObjectId("15cdcc0e14e2a44b82d2e3d7"), "user_id": "user002", "name": "B", "age": 12},
{ "_id" : ObjectId("15cdcc0e14e2a44b82d2e3d8"), "user_id": "user003", "name": "C", "age": 13},
{ "_id" : ObjectId("15cdcc0e14e2a44b82d2e3d9"), "user_id": "user004", "name": "D", "age": 14},
...
{ "_id" : ObjectId("15cdcc0e14e2a44b82d2e3d0"), "user_id": "user010", "name": "J", "age": 20},
{ "_id" : ObjectId("15cdcc0e14e2a44b82d2e3a6"), "user_id": "user011", "name": "K", "age": 21},
{ "_id" : ObjectId("15cdcc0e14e2a44b82d2e3b6"), "user_id": "user012", "name": "L", "age": 22},
Type "it" for more

1件取得

db.hoge.findOne()

出力結果

{ 
    "_id" : ObjectId("15cdcc0e14e2a44b82d2e3d6"),
    "user_id": "user001",
    "name": "A", 
    "age": 11
}

find() を見やすくするforEach(printjson)

find() では結果が1行ずつ表示となり、またType "it" for more と表示に制限がされ見づらい場合がある。

db.hoge.find().limit(3).forEach(printjson)

出力結果

{ 
    "_id" : ObjectId("15cdcc0e14e2a44b82d2e3d6"),
    "user_id": "user001",
    "name": "A", 
    "age": 11
},
{ 
    "_id" : ObjectId("15cdcc0e14e2a44b82d2e3d7"),
    "user_id": "user002",
    "name": "B", 
    "age": 12
},
{ 
    "_id" : ObjectId("15cdcc0e14e2a44b82d2e3d8"),
    "user_id": "user003",
    "name": "C", 
    "age": 13
}

こんなかんじで、改行表示してくれるので便利。limitをつけなければ全件表示してくれる。