2010年03月15日

GAE/PのDatastoreについてもっと詳しく

Datastoreはシンプルな仕組みなので、新たに使い方を覚えるのは、それほど難しくはないと思います。しかし、一般的なRDBMSとはだいぶ違うので、別モノだと思った方が良いかもしれません。

ここでは主に一般的なRDBMSとの比較で、Datastoreがどのようなものかを説明していきます。

一般的なRDBMSと大きく違うのは

  • 主キーを自由に選べない(文字列か自動採番のIDの二択)
  • 複数のテーブルをクエリで自由にJOINできない
  • フィルタ条件の不等号は同時に1つのプロパティに対してしか使えない
  • 不等号のフィルタ条件がある場合、並べ替えの1番目には同じプロパティしか使えない

JOINが使えないので、テーブル設計は正規化しすぎない方が良いようです。

主キー(ID/key_name)

Datastoreでは、主キーはシステムが自動採番する数値型のIDか、ユーザが指定する文字列型のkey_nameの二者択一となっています。Modelクラスのインスタンス作成時にkey_nameを指定すると文字列型の主キーが使われ、省略すると数値型のIDが使われます。

この主キーは、フィルタ条件や並べ替えには使うことができません。主キーで並べ替え等をする場合は、同じ値を保存するプロパティを用意する必要があります。

IDは連番ではなく、後から追加したデータが大きな数字になるとも限らないようです。

テーブル設計

Datastoreでのテーブル設計は特別な管理ツール等は使わずに、Pythonコードでdb.Modelクラスを継承したクラスを定義するだけで出来ます。基本的にDatastoreへのアクセスはこのクラスを経由して行います。一部のメンバだけを抜き出して読み書きすることはできず、Datastoreへのアクセスは一行分まるごとになります。

恐ろしいことに、エンティティごとにメンバの数や型が異なるデータモデルも定義でき、その場合はdb.Expandoクラスを継承します。このExpandoモデルは、私の感覚では気持ち悪過ぎて、いまいち有用な使い方が分かりません。

日付けと時刻

日付けと時刻を両方記録する場合には、datetime型を使います。

Pythonのdatetime型は、タイムゾーン情報を持っている場合はaware、持っていない場合はnaiveと区別され、両者が混在すると比較や演算ができないようになっています。

datetime型プロパティをDatastoreに保存すると、元がawareであってもタイムゾーン情報が失われnaiveになってしまいます。naiveなdatetimeからawareに変換するには、読み出した後にreplaceメソッドを使ってtzinfoを置き換えます。(replaceは時刻の再計算等をせずに一部の要素だけを置きかえるメソッド)

entry.datetime = entry.datetime.replace(tzinfo=UTC())

※具体的なタイムゾーンを表すクラスは提供されないので、UTC等のクラスを自分で定義する必要がある。

日本のユーザにしかサービスを提供するつもりがなければ、Datastoreには日本時間で記録しておくと、レスポンス生成時に変換が不要になるので良いと思います。

メンテナンス

GAEでは、アプリケーションを実行するサーバとDatastoreを担当するサーバが分かれているので、アプリケーションは実行できるがDatastoreに書きこめないという状況が起こります。(メンテナンス中でもサービスを続行できるように、読み出しだけは出来るようになっている)

Datastoreがメンテナンス中に書きこもうとするとCapabilityDisabledErrorという例外が発生します。しかし、掲示板などでユーザが書き込みボタンを押してからエラーを出すよりも、最初からメンテナンス中の案内が出来た方がユーザビリティが向上します。そのような目的のためにCapabilities APIが用意されています。

Capabilities APIは今のところドキュメント化されていないので、次の記事を参考にしてください。

Handling downtime: The capabilities API and testing - Nick's Blog

Capabilities APIは、Javaではまだ提供されていないようです。

2010年03月15日 【プログラミング】 | コメント(0) |

この記事へのトラックバックURL


この記事へのトラックバック
この記事へのコメント

コメントを書く
お名前: [必須入力]

メールアドレス:

ホームページアドレス:

コメント: [必須入力]

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。