GAE/J で 一対多の get、query の速度
直感的にはModelにKeyのリストを保持しておいて、Datastore.get(Child.class, keys)をやった方が速いと思っていたがInverseModelListRefを使ったqueryの方が速かった。
と言っても大した量でテストしてないんだけど、一応メモを残しておく。
ツリー構造のディレクトリのようなエンティティを200ほど登録していて、そのうち5件だけ持ってくる。
親に子のModelのキーのリストを保持しておいてDatastore.getで取得する場合と、親のInverseModelListRefを使った場合。
String ret = ""; long start = System.currentTimeMillis(); Node parent = Datastore.get(Node.class, rootNode.getKey()); List<Node> list = Datastore.get(Node.class, parent.getChildKeys()); long end = System.currentTimeMillis(); ret = "Datastore.get " + (end - start) + "ms"; parent = Datastore.get(Node.class, rootNode.getKey()); start = System.currentTimeMillis(); list = parent.getChildrenRef().getModelList(); end = System.currentTimeMillis(); ret += "\n InverseModelListRef " + (end - start) + "ms";
appengineにデプロイ直後は
Datastore.get 17ms InverseModelListRef 118ms
だけど、二回目からは
Datastore.get 15ms InverseModelListRef 8ms
となった。
念のため逆順でやってみると
InverseModelListRef 74ms Datastore.get 17ms InverseModelListRef 9ms Datastore.get 16ms
となった。
なんだかよく分からない。KeyのリストでDatastore.getする場合は大体一定時間だ。InverseModelListRefは、デプロイ直後だけ遅くて、二回目からはこっちの方が速い。
エンティティを全部消してから実行するとInverseModelListRefが遅くなったりならなかったり。ムラが激しい。
Bigtable内でデータの分散配置待ちなのか?と思ってデプロイ後にしばらく待ってから実行したら速くなった。つまりエンティティを一気に更新した直後はDatastore.get(keys)の速度は一定だけどInverseModelListRef.getModelList()は遅くなる、大量に更新した直後でなければInverseModelListRef.getModelList()の方が速い、ということでいいんだろうか。
テスト用のコードを書いたわけでもなく今書いてるアプリにちょっとしたコードを追加して測っただけなので…というか上限があるから大量のデータを突っ込んで真面目にテストするには気が引ける。
暫定の結論としては、InverseModelListRefよりList<Key>の方が速い気がしたが気のせいだった。ということで。
Keyのリストを持つのはやめて全部InverseModelListRefにしようか。
そうすると並べ替え用のプロパティが必要か…。もう少し考える。