読者です 読者をやめる 読者になる 読者になる

#slim3 のドキュメント日本語訳

id:bufferingsさんがありがたいことに翻訳してくれた。
http://d.hatena.ne.jp/bufferings/20091123/1258983438
slim3を使わない人でもappengineの特性が記載してあって良いドキュメントになっているのでappengineを使う人は必読ですよ。
いくつか知らなかったことがあったのでメモる。

クエリとインデックス 混在した型のプロパティ値は型で並び替えられる

混在した型のプロパティ値は型で並び替えられる
2つのエンティティに同じ名前で別の値型のプロパティがある場合、そのプロパティのインデックスは、エンティティをまず値型で並び替え、次にその型の中で適切な順番に並び替えます。
例えば、2つのエンティティに「age」という名前のプロパティがあって、一方は整数値、もう一方は文字列値である場合に「age」プロパティで並び替えると、
値自体には関係なく整数値のエンティティが常に文字列値のエンティティよりも前に現れます。 このことは整数値と浮動小数点値の場合に特に重要です。
データストアはこの二つの値型を別の型として扱います。
全ての整数値は浮動小数点値よりも前に並べられるため、38という整数値のプロパティは37.5という浮動小数点値のプロパティよりも前に並べられます。

appengineはスキーマレスなので同一カラムであっても型が異なる値を登録することができる。あれっでもslim3の場合は全部同じ型になるよな〜と書きながら思ったり。。。

トランザクションはSERIALIZABLE

トランザクション内のクエリや取得( get )は、トランザクション開始時のデータストアの単一で一貫性のあるスナップショットを参照することが保障されます。特に、クエリが完全で正しい結果エンティティセットを返すように、また、Transaction Isolation*2 で説明されているようなトランザクション外のクエリで起こりうる false positive*3 や false negative*4 が起こらないように、トランザクションのエンティティグループ内のエンティティとインデックス行は全て更新されます。

この一貫性のあるスナップショットビューはまたトランザクション内の書き込み後の読み込みにも拡張されます。多くのデータベースと違って、データストアトランザクション内のクエリや取得( get )は、トランザクション内で前に書き込まれた結果を参照しません。特に、トランザクション内であるエンティティが修正されたり削除されたりしても、クエリや取得( get )はトランザクション開始時のオリジナルバージョンのエンティティを返します。また、エンティティが元々は存在していなかった場合は何も返しません。


トランザクションはデータストアの一貫性のあるスナップショットを読み込むために使用することができます。
これは、ページの描画やデータのエクスポートなど複数のデータ読み込みを一貫性のある状態で行う必要がある場合に有用です。
この種のトランザクションは書き込みを行わないので、しばしばリードオンリートランザクションと呼ばれます。
リードオンリートランザクションに対するコミットやロールバックはどちらも操作を行いません。

次の例1)と例2)で返すqueryの結果は異なることを意味する

例1)beginTransactionあり

Transaction tx = Datastore.beginTransaction();
CustomerMeta c = new CustomerMeta();
List<Customer> customers = Datastore.query(c)
    .filter(c.user.equal(user))
    .asLIst();
List<Customer> customers2 = Datastore.query(c)
    .filter(c.user.equal(user))
    .asLIst();
Datastore.rollback(tx);


例2)beginTransactionなし

CustomerMeta c = new CustomerMeta();
List<Customer> customers = Datastore.query(c)
    .filter(c.user.equal(user))
    .asLIst();
List<Customer> customers2 = Datastore.query(c)
    .filter(c.user.equal(user))
    .asLIst();

例1)のcustomers は必ずcustomers2と同じ結果を返す。
例2)のcustomers はcustomers2と異なる結果を返す時がある。customers2を実行する間にほかのセッションにてデータが追加されていた場合にそれを反映する。

追記

@higayasuoさんから下記を教えていただきました。私の認識に誤りがあったようです。

  • トランザクションが効くのはancestor queryだけなので通常のqueryはトランザクション中に実行しても一貫性はありません #appengine
  • tx中の同一EGないのgetも一貫性は保たれます #appengine

このあたりは大事なところなので動きを抑えておきたいところですね。