スティルハウスの書庫の書庫

はてなダイアリーで書いてた「スティルハウスの書庫」を移転してきました。

大きなコンポジットインデックスは自作した方が早いかも

大きめのコンポジットインデックスを作ろうとしたら、管理コンソールのインデックス状態が「Error」となってしまいました。大きめといっても、2M件くらいなので“爆発”状態ではないのですが。。

MLで問い合わせしてみました。

http://groups.google.com/group/google-appengine-java/browse_thread/thread/18e26802d24f6d02#

GoogleのJasonさんは「もう一回試せば今度はうまくいくよ!」と言うけど、そんなもんですか〜。

このコンポジットインデックスにはもうひとつ問題があって、テスト用に作った小規模の環境で動作を試したところ、複数プロパティに対するクエリがうまく動きません。うち1つのプロパティに不等式フィルタを追加すると、原因不明のエンティティの取りこぼしが発生してしまいます。取りこぼされるエンティティ自体は他のエンティティと表面上の違いはまったくないので、ナゾ。

その他にも、コンポジットインデックスは何かと使いにくいです。

  • インデックス構築の進捗状況がわからない(上記の大きなやつで2日くらいかかった)
  • インデックスの削除はPython SDKでしか実行できない
  • インデックスの中身が見えない、規模が分からない

そんなわけで、コンポジットインデックスに相当するテーブルを追加することにしました。例えば、

  • 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がどこかに書いてあった気もします)。こうしてインデックスを自作すれば、

  • インデックスの中身が見える
  • 自分で構築するから状況も規模も把握しやすい
  • インデックスの削除や修正、作り直しもできる

ただしデメリットは、

  • インデックス対象のエンティティの更新に合わせて、インデックス用エンティティの更新も自前で実行する必要がある
  • 同様のクエリが増えるたびにテーブル作るのは面倒。。重要な用途のみにとどめたい
  • インデックスのストレージ領域は課金対象外だが、自作すると課金対象になる

といったところです。

#こうして、だんだんスキーマ設計の発想が「ジョイン脳」から「スキャン脳」に
#変化しつつあるような気がします。