app engine ja night kansai 2「Query & Index」メモ

bpstudy33と同日に開催されたajnk2について、@bufferings さんのUST録画をみながら理解したことをメモ。Cacooで描かれたという図がすごく見やすく、わかりやすかったです。bufferingsさんのブログにpdfとustへのリンクあり。
#appengine ja night in kansai 2 ( #ajnk2 ) を開催しました! - bufferings

おさらい

  • DatastoreによってBigTableに永続化
  • Pathっていうのは祖先キーとかのEntityGroupの情報
  • Queryは単一のKindのみ扱える
  • スキーマが一定でなくてもよいことを「ソフトスキーマ」という
  • プロパティ自体が存在しない(=Unset)

Bigtableからのデータ取得

三種類の取得。a,b1,b2,b3,cとエンティティがある場合

  • Readは1エンティティの取得。(aのみ)
  • Prefix Scanはb1〜b3のような前方スキャン
  • Range Scanは b〜dのような範囲スキャン

Datastoreからのデータ取得

  • Get ー KeyのAppID + Path情報から取得
    • (参考)Batch Get 複数のkeyでまとめてEntityをGet
  • Query ー  Kind、Filter, Sort Orderにより結果リスト(=Index)から取得
  • Indexは、使用するすべてのクエリに大して必要。RDBのような問い合わせ時の計算、集約、Joinは不可。取得はエンティティ全部、もしくはキーのみのいずれか。Entityを更新すると関係するインデックスが更新される。

Query

  • Queryの構成
    • Kindを指定
    • 0個以上のフィルタを指定(=, <=, <, >, >=, !=, IN)
    • 0個以上のソート順を指定(ASC, DESC)
      • KindlessQueryはKindを指定しない特別なクエリ
  • 制約(クエリの仕組みを知れば制約の理由がわかる)
    • フィルタ/ソートには、プロパティ自体が存在してなければならない
    • 不等式フィルタが使用できるのは1つのプロパティのみ
    • 不等式フィルタで使用されているプロパティはほかのソート順よりも先にソートする

Index

  • インデックスには3種類ある。
    • Kind Indexー自動で作成される。特定のKindの全Entityを取得するときに使う
    • Single Property Indexー自動で作成される。Kind IndexにPropertyName とPropertyValueが入っている。昇順と降順それぞれのインデックステーブルが作成される。
      • 等式ならPrefixスキャン
      • 不等式+不等式ならRangeスキャン
    • カスタムインデックス
      • 開発者が独自に定義するインデックス。(Javaならdatastore-indexes.xmlに定義する情報)
      • IndexIdというのがあって、それがカスタムインデックスの定義とひもづいている。
      • Ancestorは祖先とかの情報

Merge Join

  • 複数のプロパティであっても、等式フィルタのみならCustom Indexを定義しなくてもQueryを実行できる
    • Single Property Indexをzig-zagアルゴリズムによりマージしながら検索する
    • ただし、データ量が多いとエラーになってしまう
    • Custom Indexが定義済みならMerge JOINは行われない

Key Only Query

  • キーだけを返すクエリ。 quotaを節約できる。
  • 例えばエンティティ削除の時はキーだけでよい

Queries on Key

  • キーに対してのフィルタ。(等式はget()でよいので、不等式)
  • キーの降順ソートにはCustom Index定義が必要

Kindless Query

  • Kindを指定しないQuery
  • AncestorとKeyフィルタのみ指定可能(JavaはAncestorのみ

Not-Equalフィルタ(!=)、INフィルタ

  • NotEqualフィルタは内部的には不等式フィルタの結果をマージするので、不等式フィルタと同じ制約あり
  • INフィルタは複数の等式フィルタをマージする
  • どちらも複数のQueryを実行するので通常のクエリより遅い

Ancestor Query

  • EntityGroupの祖先を指定してEntityを取得するQuery
    • Kindless Ancestor Query(Kind指定なし。Javaは不可)
    • Ancestor Query (Kind 指定あり。)
    • -

MVP(Multi Value Property)

  • favorite=["apple", "google"]のように、ひとつのプロパティが複数の値を持てる。
  • インデックス爆発とは、MVPに対するフィルタを複数もつカスタムインデックスを作成した場合に、1エンティティのインデックス上限5000を超えてしまうこと。

感想

Slim3のDatastoreまわりのメソッドをひととおり調べてて、なんでこうなってるんだろうと思うことが多々あったのですが、今回ちゃんと仕組みを知れたことで、腑に落ちたことがたくさんありました。ありがとうございました。