Google App Engine についてあなたが多分知らない10のこと.

Google App Engineのブログより.なんかスターとかいただいたので,もう少し丁寧に訳してみる.

Google App Engine についてあなたが多分知らない10のこと.

1. アプリケーションのバージョンは数字ではなく文字列である.

app.yamlやappengine-webのほとんどの例では,versionフィールドに数字をあたえているが,これは単なる慣習にすぎない.バージョンにはURLで許されているものであれば,任意の文字列が使用できる.たとえば,"live" や "dev" をバージョンに使うと,アプリケーションは,"live.latest.yourapp.appspot.com" や"dev.latest.yourapp.appspot.com" でアクセスできる.

2. 複数のバージョンのアプリケーションを同時に利用できる。

1で述べたように,App Engineは複数のバージョンのアプリケーションを同時に実行することを許している.すべてのバージョンは,データストアとmemcacheを共有するが,異なるインスタンス上で実行され,異なるURLを持つ.デフォルトのバージョンのURLはは,yourapp.appspot.com となるが,すべてのバージョンは, version.latest.yourapp.appspot.com でアクセスできる.複数のバージョンを利用できる機構は,新しいバージョンをリリースする前に,実データで実環境でテストする際に特に役に立つ.
さらにあまり知られていない事実がある.それは,一つのアプリのすべてのバージョンが同じランタイムを使う必要はない,ということである.あるバージョンでJavaを使い,別のバージョンでPythonを使っていてもまったく問題ない.

3. JavaランタイムではJavaバイトコードになるものであれば任意の言語を使用できる.

Javaランタイム」とは呼ばれているが,JVMバイトコードコンパイルされる言語であれば,どんなものでも実行することができる.実際,JRuby, Groovy, Scala, Rhino,Quercus,さらにはJython(!)
をApp Engineで動かしている人がいる.Javaランタイム上で,何が動いて何が動かないかをコミュニティがまとめたものが,
このwikiにある.

4.'IN','!=' 演算子を用いたキュエリは,内部的に複数のキュエリに展開される

'!=' は '<' と '>' に展開され,結果が合成される.

name IN ('Bob', 'Jane') 

は下の二つに展開され,結果が合成される.

name == 'Bob'
name == 'Jane'
5. データストアに対するリクエストはバッチで行うことができる.

リクエストの処理にはオーバヘッドがあるが,バッチで行うことでこのオーバヘッドを短縮することができる.
次の例は,MyModelの集合からcolorがold_favoriteのものを100個とりだし,new_favoriteに置き換えるもの.

for entity in MyModel.all().filter("color =",  
      old_favorite).fetch(100):
    entity.color = new_favorite
    entity.put()

これを下のように書き換えるとずっと速くなる.

updated = [] 
for entity in MyModel.all().filter("color =", 
      old_favorite).fetch(100): 
    entity.color = new_favorite 
    updated.append(entity) 
db.put(updated)
6.データストアの性能は,中に収めたエンティティの数と関係ない

1つのApp Engineのアプリケーションのエンティティは,1つのBigTableのtableに置かれている.queryの実行にかかる時間は,(3でのべたような場合を除けば)基本的に,結果の数に比例する.

7. インデックスを作るのにかかる時間は,サイズにだけ依存する訳ではない.

インデックスの作成はキューイングされて,中央のシステムが一括して行う為,作成時間には待ち時間がふくまれる.

8.管理コンソールの'Stored Data'で参照できる値は1日に一度しか更新しない.
9.app.yamlやappengine-web.xmlに書く順番には意味がある.

よくある面倒な間違いに,アプリケーション設定ファイルを書く際に,このファイルが上から順番に処理されることを忘れてしまう,というものがある.たとえば,remote_apiをインストールする際に,こう書いてしまうことがよくある.

handlers:
- url: /.* 
  script: request.py 
- url: /remote_api 
  script: $PYTHON_LIB/google/appengine/ext/remote_api/handler.py 
  login: admin

一見問題なさそうだが,ハンドラは順番に評価されるので, すべてのリクエストに対して(remote_api に対しても!) request.py が先にマッチしてしまい,request.pyが処理してしまう.request.pyはremote_apiを知らないので,404 Not Found errorがリターンされることになる.すべてにマッチするハンドラは一番最後に来るようにしなければならない.

Java ランタイムでもこれは同じだが,さらに,appengine-web.xmlに書かれるstatic ファイルハンドラが,web.xmlにかかれる動的ハンドラよりも先に処理されることに注意する必要がある.

10. GQL文字列は毎回組み立てる必要は無い.

文字列を直接埋め込まずにパラメータ名で置換するように書くことができる.

q = db.GqlQuery("SELECT * FROM People "
    "WHERE first_name = :first_name " 
    "AND last_name = :last_name", 
    first_name=first_name, last_name=last_name)

さらにキュエリに対してパラメータを何度もバインドすることもで
きる.

q = db.GqlQuery("SELECT * FROM People "
    "WHERE first_name = :first_name "
    "AND last_name = :last_name")
for first, last in people:
    q.bind(first, last) 
    person = q.get() 
    print person