データストアのクエリ

PythonのクエリAPI

キーに対するクエリ

本当に久しぶりな感じがしますが、App Engineのお勉強に戻ります。

これまではクエリを発行すると完全なエンティティが取得出来ました。でもエンティティのフィールドが多かったり、サイズが大きかったりすると結構な負荷になります。そのため、Pythonではエンティティのキーだけをクエリで取得することが可能になっています。

GQLで書く場合はこんな感じ。

query = db.GqlQuery('SELECT __key__ FROM Player');


Queryクラスを使う場合はこんな感じ。

query = db.Query(Player, keys_only=True)


でもキーだけ拾って目的のエンティティを探し当てることなんて出来るのかな?

インデックスの紹介

ある意味一番知りたかったところです。心して学習します。

前にも書きましたが、App Engineのデータストアで可能な操作はインデックスのスキャンのみです。GQLはSQLのような表記ですが、RDBとはまったく構造がことなります。

たとえば以下のようなGQLを実行するとします。

SELECT * FROM Player WHERE level = 7


これはPlayerという種別のエンティティの内、levelが7のものを取得するGQLです。このGQLを発行する際、データストア側では以下のようなインデックスが用意されています。


これはエンティティキー (app-idと種別名、エンティティIDで構成されています) とlevelプロパティの一覧表 (インデックス列) です。levelプロパティの昇順でソートされています。

上記クエリが発行されるとデータストアAPIは上記インデックス列を先頭からスキャンしていきます。最初にフィルタ (WHERE level = 7) に合うインデックスを見つけます。今回は一件しかありませんね。でも複数存在する場合もあるので、さらに先に進みます。そしてフィルタに合わないインデックスを見つけた時点でスキャンは終了。フィルタに合うインデックス列のエンティティキーから全てのエンティティをBig Tableから取得して、呼び出し元に戻します。


そうなんです。データストアは本当に単純なスキャンしかしていないのです。これはちょっと目から鱗といいますか、面白い内容です (かつ分かりやすい) 。


ここで重要なのがインデックスが、フィルタに現れるプロパティでソートされているということ。ソートされていないと上記のようなスキャンは出来ません。

ではこのようなインデックス列は誰が作ってくれるんでしょうか?それはApp Engineがエンティティの追加・削除・変更の度にインデックス列を更新します。つまり、インデックス列を常にスキャン可能な状態に保つわけです。


上で示した例はインデックスにプロパティが一つしかないパターンでした。App Engineは全エンティティ種別の全プロパティ名に対して昇順、降順にソートされたインデックス列を自動で生成、更新します。このプロパティが一つしかないインデックスのことを自動インデックスといい、自動インデックスを使ってスキャンするようなクエリのことをシンプルなクエリと呼びます。

シンプルなクエリを発行するのに、特別な準備は必要ないわけです。


これとは別に、フィルタ条件に複数のプロパティを使うなど、複雑なクエリを発行する場合、あらかじめ開発者がインデックス列を作らせるための設定ファイル (index.yaml) を用意する必要があります。


ちなみにインデックス列が存在しないとクエリが失敗します。結構厳しいですね。