大きなコンポジットインデックスは自作した方が早いかも
大きめのコンポジットインデックスを作ろうとしたら、管理コンソールのインデックス状態が「Error」となってしまいました。大きめといっても、2M件くらいなので“爆発”状態ではないのですが。。
MLで問い合わせしてみました。
http://groups.google.com/group/google-appengine-java/browse_thread/thread/18e26802d24f6d02#
GoogleのJasonさんは「もう一回試せば今度はうまくいくよ!」と言うけど、そんなもんですか〜。
このコンポジットインデックスにはもうひとつ問題があって、テスト用に作った小規模の環境で動作を試したところ、複数プロパティに対するクエリがうまく動きません。うち1つのプロパティに不等式フィルタを追加すると、原因不明のエンティティの取りこぼしが発生してしまいます。取りこぼされるエンティティ自体は他のエンティティと表面上の違いはまったくないので、ナゾ。
その他にも、コンポジットインデックスは何かと使いにくいです。
そんなわけで、コンポジットインデックスに相当するテーブルを追加することにしました。例えば、
- WHERE a == 'Foo' && b > 0 && b < 100 ORDER BY b asc, c asc
という感じのクエリを実行したい場合、
- a + b + c
を文字列で連結したプロパティsortKeyと、インデックス対象のエンティティのKeyを持つエンティティMyIndexを作ります。このエンティティに対して、
- WHERE sortKey > 'Foo+000' && sortKey < 'Foo+100' ORDER BY sortKey asc
みたいなクエリを投げれば、コンポジットインデックスは不要になります(というか、こんなtipsがどこかに書いてあった気もします)。こうしてインデックスを自作すれば、
- インデックスの中身が見える
- 自分で構築するから状況も規模も把握しやすい
- インデックスの削除や修正、作り直しもできる
ただしデメリットは、
- インデックス対象のエンティティの更新に合わせて、インデックス用エンティティの更新も自前で実行する必要がある
- 同様のクエリが増えるたびにテーブル作るのは面倒。。重要な用途のみにとどめたい
- インデックスのストレージ領域は課金対象外だが、自作すると課金対象になる
といったところです。
#こうして、だんだんスキーマ設計の発想が「ジョイン脳」から「スキャン脳」に
#変化しつつあるような気がします。