テスターですが何か?

ホビープログラマ略してHPです

Azure Table Storage のハマリどころ

leave a comment »

Windows Azure Platformを使い初めて半年以上、「SQL Azureを使ったら負けだと思っている」をスローガンにデータストアにはAzure Storage Serviceを使ってきました。RDBに比べると色々違いがあり、ハマリどころがいくつかあるのでまとまった時間が作れたこのタイミングでまとめたいと思います。

リレーショナルなデータではない

いちばんの違いはここですかね、リレーショナルなことを(勝手に)想定してデータモデルを作ることは出来ますが、リレーショナルに扱うことができません。つまりJOINができません。そのため、以下のような親子関係にあるデータを結合して取得するLinq構文はTable Storageでは実行できません。SQL Server + EntityFrameworkでは当たり前に実行できますが。

           var q = from t in context.CreateQuery("TableName")
                   join m in context.CreateQuery("TableName1") on t.Key equals m.Key
                   where t.Value == Value
                   select t;

じゃ、どうするかというと考えられるのは2通りあります。

  • 親のデータを取得後、foreachを利用して子のデータを取得する(何度もTableへアクセスするので遅くなりますが)
  • 親子関係のデータ構造にしない、データ重複を許容し取得・表示したいデータの構造でデータを保存する

強引にJOINする方法もあるようです。以下サイトの内容を参考にしてください。

Azure Tableによるデータ検索 – エンティティの結合(Join)

利用可能なLinq式に制限がある

有名な話ですがTable StorageではほとんどのLinq式が利用できません。利用できるのはFirst/FirstOrDefault/Takeくらいで、Orderby/Count/Max/Min などは利用できません。MSDNにきちんと記載されています。

クエリ演算子 (テーブル サービスのサポート)

こちらのエントリーでもまとめているので、参考にしてください。Linq to TableStorage としてサポートされていないので、ToList/AsEnumerableを使用してLinq to Objectとしてメモリ上でクエリを実行するしかありません。もしくは、あらかじめ集計結果のデータを別エンティティで保存しておきそのデータを使用するしかないでしょう。

1回のクエリで取得できるデータは1000件まで

ホワイトペーパー「Windows Azure Table – テーブル ストレージのプログラミング」の「6.2 継続トークン」に明記されています。逆に言うとそこにしか書いていないので、知らずに大ハマリになることがあります。LinqによるTableStorageへの直接の集計メソッドを実行することができないため、一旦データを取得して集計しようとします。例えば1時間ごとのデータ(365日×24時間=8760件)を月毎に集計しようとします。が、Table Storageから1回のクエリで取得できるデータは最大1000件なので、8760件のデータを取得しようとしても1000件しかデータは返ってきません。その際、クライアントには継続トークンが返ってくるようなので、継続トークンを使用して次の1000件のデータの取得を行います。(未検証)

上記例のようにあらかじめデータ件数がわかっている場合には、1回の問い合わせが1000件未満になるようにクエリを実行したほうが、処理はわかりやすくなるかもしれません。

1トランザクション制御可能なデータは100件

ホワイトペーパー「Windows Azure Table – テーブル ストレージのプログラミング」の「4.9 エンティティグループトランザクション」に明記されています。逆に言うとそこにしか書いていないので、知らずに大量データのトランザクション制御を行おうとすると例外が発生します。他にも

  • エンティティサイズが4MB
  • 同一テーブルの同一パーティションキー

の制限があります。

これはストレージの仕様上どうしようもない部分なので、100件未満となるデータのかたまりごとにトランザクション制御を行うか、件数が可変であれば100件単位でトランザクション制御を行うしかありません。

エンティティグループトランザクションを設定しないとデータ挿入が非常に遅い

個人的にはここにいちばんハマリました。世の中にはTableStorageのサンプルがたくさん公開されていますが、エンティティグループトランザクションが設定されているサンプルはほとんどありません。そのサンプルを参考に大量データの挿入を行うといつまで経っても処理が終了しません(笑)

1日24時間分のデータの挿入に1分近くかかっていてどうにもこうにも早くならなかったんですよ。結局、SaveChangesメソッド実行時に、SaveChangesOptions.Batch引数を指定するだけで一気にデータ挿入が早くなります。

いろいろ検証を行なってこのブログをまとめていますので、参考にしてください。

まとめ

TableStorageのようなクラウド上のKey-ValueストレージはRDBではありません。RDBでできていたことがクラウドストレージでできると考えてはいけません。違うストレージなので、違うストレージであることを理解して設計を行う必要があります。RDBでできていたことをそのまま行いたい場合はSQL Azureを利用するといいでしょう。

Written by david9142

2011年12月30日 @ 5:16 PM

カテゴリー: WindowsAzure

Tagged with ,

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

%d人のブロガーが「いいね」をつけました。