メモ。
新しいKindをバックアップ対象に加えたところ、従来バックアップしていたKindに比べて格段に時間がかかった。新しくバックアップしたKindは総データ量は小さいのだが、件数が格段に多い。Google App Engineのbulk loaderは、データ量よりもデータ数によって所要時間がかかるということだろうか?
データ数[件] | 合計データ量[bytes] | 所要時間[秒] | 備考 |
---|---|---|---|
857 | 6,954,557 | 181.8 | |
858 | 6,992,591 | 178.5 | |
923 | 7,521,286 | 172.4 | |
991 | 8,103,808 | 215.9 | |
36,737 | 7,485,726 | 2,770.2 | このデータだけKindが異なる |
件数の少ないマスタデータのバックアップには有効だが、時間経過と共に増えていくトランザクションデータを落とすのはさほど現実的でないかも。もちろん全件まとめて落としてくるという使い方自体がDatastoreの使い方として間違っているというのはある。
トランザクションデータの分析・処理もGAEに載せることが必要なんでしょうね。となるとR on Google App Engineとかできると嬉しそうだ。
他にはプロパティの型に依存するという可能性がある。
古いKindはほぼIntegerだが、新しいKindはDateとMetaDataが記憶容量の大半を占めている。DateをCSVに変換する過程で時間がかかっているのかもしれない。ただ、それだけで処理時間が10倍以上に膨れ上がるとは考えにくい。
追記(新展開編)
そしてBigtable/Datastoreの実装詳細を理解すれば、この手の話はアタリマエのこととして認知できそうな気がしないでもない。単に通信回数増加でも説明できるかも。でも多分bulk loaderの実装によるところが多そう。
まぁデータ件数37倍で時間13倍に抑えられていると考えると、優秀な実装にも見えますね。でもデータ量は増えていないんですがね。
データ容量よりデータ件数に依存して遅くなる=通信回数なりレコードごとの定型処理なりが悪いはずで、本来G社が得意な領域のような気がする。コード見たい。
いやちょっと待て、Dashboard見たらbulk loaderが走っている間に1.3reqs/secも継続して受信していることになっている。1レスポンスに2KBくらい載せてビシバシHTTP通信していたってことか!そりゃ遅いわ。Bigtable関係ないし。
追記(解決編)
先述のとおり、Dashboardでbulk loaderが多数のリクエストを送っていることが確認できた。1.3[リクエスト/秒]といったところか。
POSTのレスポンスにデータを載せて持ってくる実装になっているようだが、1レスポンスに10件しか載せていない。以下はbulk loaderのDEBUGログからの引用。
[DEBUG 2011-01-29 14:13:08,308 bulkloader.py] [WorkerThread-5] DiffInfo-ASC(datastore_types.Key.from_path(略) to None] Transferred 10 entities in 0.6 seconds
bulk loaderの--batch_sizeオプションを使えばもっとまとめて通信することも可能らしいので、より高速化できそう?ということで試す。
まず1000を指定したところ、サーバがエラーを返してきて処理が止まった。何らかの内部エラーが生じたらしい。
[WorkerThread-8] Backing off due to errors: 1.0 seconds
サーバ側のログを見ても原因がよくわからない。とにかく件数を増やしすぎたことがきっかけではあるだろう。
com.google.apphosting.api.ApiProxy$ApplicationException: ApplicationError: 4: no matching index found.
次に100を指定したところ、215秒かかっていたバックアップが102秒で終わったことを確認。新しいKindも--batch_size=200にすることで2,770秒が1,864秒になった。
爆速とは行かないが処理時間の大半を圧縮することはできた。ひとまずは困らないだろう。