はたしてどういうレベルで書けばいいのか悩ましいところですが、Azureストレージの話。
Windows Azure PlatformにはRDBMSに代わるデータ保存用のストレージサービスが提供されていて、それを「Azure Storage」と呼びます。
これとは別に「SQL Azure」というSQL Server互換のRDBMSも利用できるのですが、どちらかというと既存アプリのクラウド対応を促進するために用意されたもの、といった印象で今のところは本筋ではなさげ。クラウドのメリットのひとつでもあるスケーラビリティが失われるのが大きいと思われます。まぁ、単純にデータベースが巨大になると重くなりますからね…。
話を戻して、Azureストレージですが、マトモに触ったのは今回のAzumeが初めて。
といっても、Table、Blob、Queueと3種類あるうちのTableしか使っていないので、今回はTableにまつわる雑感をば。
Tableストレージというのは、NoSQLの一種で、いわゆるKVS(Key-Value Store)タイプのデータ格納領域です。
スケーラビリティがあって、読み書きのスピードも速くて、というアレ。
その代わり、結合や集計などはできないので、別途アプリ側に実装が必要です。
TableストレージにはPartitionKeyとRowKeyの組み合わせでユニークなキーとなるようにデータ格納していきます。
Table内のレコードには追加/更新時に自動的にTimestampがセットされるので、これにより楽観的排他制御が可能となります。
トランザクションはPartitionKey単位に扱われるようで、PartitionKeyが同一の複数レコードを一括更新しようとした場合、一件でも更新に失敗した場合は全データの更新がロールバックされるようです。
これはスケーリングの話とも絡んでいて、PartitionKeyが異なるデータは物理的に同一の場所に存在する必要はないため、データが多くなってくるとPartitionKey単位で自動的に分割されたりするようです。
面白いのは、前述の必須プロパティ以外はレコード毎に自由なレイアウトを設定できることで、やろうと思えばひとつのTableに全ての情報を突っ込むこともできてしまいます。
結果的に、あるキーでは値が入っていたプロパティでも、別のキーでは値が空っぽ(null)だったり、という状況が発生しますが、その辺りの管理は参照/更新するアプリケーションにお任せ、という考え方。
試しに、Table上のあるプロパティにレコード毎に異なるデータ型の値を入れてみたところ、特に問題なく格納できる様子。(ただし、開発時に利用するAzure SDK付属のDevelopment Storageで同じことをやるとテーブルが開けなくなるようなので要注意)
あるアプリケーションではint型で使っているプロパティを、別のアプリケーションではDateTime型で使う、などといったトリッキーなことまでもができてしまうということで、中に何が入っているか分からない、という意味ではまさに純粋な入れ物といった感じですが、アプリケーションと一体化していて単体では制約すらかけられない様は、DOA志向な技術者からみるとイケてないように思えるかもしれません。
個人的にもRDBに比べるとデータの独立性が損なわれている印象は否めませんが、結局は用途の問題ということになりそうです。
RDBを単なるISAMとして使っているシステムも巷にはごろごろ転がってますしw
ちなみに、Azumeの場合はアカウントマスタと休日マスタ、それとユーザ別の勤怠データをそれぞれテーブルとして分割しています。
WCF経由でアクセスする場合はTable上のプロパティ名がそのままC#やVBのプロパティ名としてクラスを作ってアクセスすることになりますので、キー毎のスキーマ定義=エンティティクラスの作成という作業となります。
また、Tableストレージそのものというか物理的には常にnull許可の状態なので、論理的にnullを許容するかどうかはエンティティクラス内のプロパティ型がNullableかどうかで決まってきます。
アクセスの方法ですが、基本的にはLINQで必要なデータを抽出して使うイメージになります。
キー以外のプロパティによる抽出もやればできますが、前述のトランザクションの関係もありますし、パーティションを跨った検索がご法度というのは常識レベルの話だと思いますので、PartitionKey(あるいは+RowKey)の抽出条件は必須と考えたほうが良いでしょう。
いずれにしても、Tableストレージの利用に際してはキー値の設計がポイントになりそうです。
ちなみにAzumeでは、アカウント登録の際にランダム文字列を生成して、これを個別の勤怠データのTable名およびPartitionKeyとして使っています。
本来ならアカウント毎に勤怠用のTableを用意する必要はないのですが、万一Tableが壊れた場合の被害を最小限にするために個別に分けてあります。
長くなってしまったので、ひとまず今回はこの辺で…。