2009/12/16

Google App Engine エンティティとトランザクション

本日は至極まじめな話

GAE でデータストアを扱う場合、トランザクションには縛りがあって、エンティティグループ内でしか1トランザクションとして扱えない。

このエンティティグループというのが曲者で、こいつらは1トランザクションとして作成/更新/削除できるが、データストアとしては分散できないため、あまり大きなエンティティグループを作成するのはよくないらしい。

話は前後するが、このエンティティグループというやつは、DBモデルの親子関係を結ぶことで(つまり共通の親を持つ)ことで作成される(相手へのリファレンスとは別物)。
エンティティグループでないトランザクションは、一度に処理できない。
以下、a,b は同一エンティティグループに属さないため、1トランザクションで処理できない。

class Sample(db.Model):

counter = db.IntegerProperty()

def inc_counter(a, b):
a = Sample(counter=a)
b = Samble(counter=b)
a.put()
b.put()

db.run_in_transaction(inc_counter, 1, 2)
 
ビックテーブルの性格上、ある程度しょうがないとして推奨例が
http://code.google.com/intl/ja/appengine/docs/python/datastore/keysandentitygroups.html
にこっそり書いてあります。
  • トランザクションに必要なときにだけ、エンティティ グループを使用します。その他のエンティティ間の関係には、ReferenceProperty プロパティと、クエリで使用できる Key 値を使用します。
大前提:
トランザクション処理が必要ないときは、エンティティグループを使用しないで、リファレンスを使用する。
例外:
トランザクションが必要な場合、エンティティグループとする。

Aさん から Bさん へお金の移動をしたい。でも100万人もユーザーがいる場合、全員をエンティティグループにしたくない。
この場合、Aさん Bさん の親を仮に作成してエンティティグループにし、1トランザクションで実行した後、親エンティティを消せばいいのかな?。ビックテーブルでは親が消えても子のエンティティは存続するし。
簡単に試せそうだけど、面倒くさいので必要になったとき検証します。ぐだぐだ...

1 件のコメント:

  1. 「エンティティグループへの加入は、エンティティ生成時のみ」という記述を、何かで見たような気がします
    (ソースが見当たらなくて申し訳ないですが)

    返信削除