テスターですが何か?

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

AzureTableStorageの高速化(3) -打倒SQLAzure!!!-

leave a comment »

「オレたちのAzureTableStorageがこんなに遅いわけがない!!」というテーマで始まった激短集中連載ですが、今回のエントリーをもって最終回です。遅くて遅くて仕方がないTableStorageが少しでも速くなればいいなと思って始めた企画ですが。前回のエントリーでまさか300倍のパフォーマンスアップができるとは思いませんでした。

 

前回までのまとめです。

Azure TableStorageの高速化(1) -エンティティグループトランザクション-

→ エンティティグループトランザクション必須、これだけで性能が100倍になる

Azure TableStorageの高速化(2) -処理の並列化-

→ Parallelクラスを利用して処理を並列化、性能300倍も可能

 

連載の最後に、SQLAzureとの性能比較を行いたいと思います。

 

検証環境

  • Webロール
  • VMサイズ: S
  • インスタンス数: 1
  • SQL Azure WebEdidion

 

参考記録

前回のエントリーでたたきだしたAzureTableStorageのデータ数に対する処理時間です。

100エンティティ(直列処理) → 0.18秒

10,000エンティティ(並列処理) → 6.8秒

 

検証プログラム

WebロールのASP.NET MVC3で10,000件のデータを挿入するプログラムです。コントローラーから文字列だけを返し、画面にデータ挿入にかかった時間を表示します。前回のエントリーで作成したプログラムを、SQLAzure用にEntityFramework4.1を使用します、もちろん処理は並列化しています。DbContextクラスもスレッドセーフではないので(たぶん)、100件単位で別インスタンスで100トランザクション実行しています。誰かEntityFrameworkで大量データ挿入を1トランザクションで並列化・高速に行う方法をブログで書いてくれないかなぁ。(´・ω・`) 自分でも調べようかと思いましたが、時間がなかったです…

OreModelsSQLAzure.cs

 
    public class OreModelsSQLAzure
    {
        public int Id { get; set; }

        public string PartitionKey { get; set; }

        public string RowKey { get; set; }

        public string Data { get; set; }
    }

    public class OreContext : DbContext
    {
        public DbSet<OreModelsSQLAzure> OreModel { get; set; }
    }

 

OreDaoAzure.cs

 
    public class OreDaoAzure
    {
        private OreContext context = new OreContext();

        public void AddOre(IEnumerable<OreModelsSQLAzure> ore)
        {
            foreach (var m in ore)
            {
                context.OreModel.Add(m);
            }
            context.SaveChanges();
        }
    }

 

HomeController.cs

 
        public string Index3()
        {
            var Models = new List<OreModelsSQLAzure>();
            OreModelsSQLAzure OreModel;

            for (var i = 0; i < 100; i++)
            {
                OreModel = new OreModelsSQLAzure();
                OreModel.PartitionKey = "oretachinoAzureTableStoragegakonnaniosoiwakeganai";
                OreModel.RowKey = Guid.NewGuid().ToString("N");
                OreModel.Data = "oretachinoAzureTableStoragegakonnaniosoiwakeganai" + i.ToString();

                Models.Add(OreModel);
            }

            var sw = new Stopwatch();
            sw.Start();
            Parallel.For(0, 100, i =>
            {
                var Dao = new OreDaoAzure();
                var m = Models.Skip(i * 100).Take(100);
                Dao.AddOre(m);
            });
            sw.Stop();

            return string.Format("処理時間:{0}ミリ秒", sw.ElapsedMilliseconds.ToString());
        }

 

結果(100レコードずつ100トランザクション)

1回目 7.59秒
2回目 5.23秒
3回目 5.34秒
4回目 6.78秒
5回目 4.77秒
平均 5.94秒

SQLAzure強いっす・゚・(つД`)・゚・ その差はわずかですが、AzureTableStorage(平均6.8秒)よりもパフォーマンスが上でしたね。

となると、1,000レコードずつ10トランザクションを並行で実行した場合は?直列で10,000レコードを1トランザクションで実行した場合は?と気になりますよね。ではいろんなパターンでやってみましょう。

 

結果(1,000レコードずつ10トランザクション)

1回目 32秒
2回目 30秒
3回目 33秒
4回目 28秒
5回目 30秒
平均 30.6秒

 

結果(10,000レコード1トランザクション)

※タイムアウトで処理が完了せず

 

結果(10レコードずつ1,000トランザクション)

1回目 6.1秒
2回目 4.3秒
3回目 4.8秒
4回目 4.8秒
5回目 4.8秒
平均 4.96秒

 

1トランザクションのデータ件数が増えるにしたがってパフォーマンスが大きく低下します。これはSQLAzureの問題というよりもEntityFrameworkの問題だと思います。10,000レコードを1トランザクションで実行すると、ローカルでも70秒近くかかりました。まぁ、数千件を一括処理するような処理はC#,VBではなくストアド実装するでしょうから、そんなに問題にはならないでしょうが。EntityFrameworkのちょっとしたトラップでしょうね。

う~ん、サーバー/サービスの大量データ登録パフォーマンスの検証をしたかったんですが、クライアントライブラリの検証になりつつありますw

 

最後に一番プレーンなパターンを実行して締めくくりましょう。直列で100件のデータを登録します。

100件のデータを1トランザクションで実行

1回目 0.28秒
2回目 0.30秒
3回目 0.35秒
4回目 0.29秒
5回目 0.30秒
平均 0.30秒

キタ━━━━━━(゚∀゚)━━━━━━ !!!!!

キタY⌒Y⌒(゚∀゚)⌒Y⌒(。A。)⌒Y⌒(゚∀゚)⌒Y⌒Y !!

キタ Y⌒Y⌒Y⌒Y⌒Y⌒Y⌒(。A。)!!!

キタ─wwヘ√レvv~(゚∀゚)─wwヘ√レvv~─ !!!

キタ─wwヘ√レvv~【゚∀゚】─wwヘ√レvv~─ !!!!!

キタ━━━(゚∀゚)━( ゚∀)━( ゚)━( )━( )━(゚ )━(∀゚ )━(゚∀゚)━━━!!!!!

キタ━━ヽ(゚∀゚)ノ━( ゚∀)ノ━( ゚)ノ━ヽ( )ノ━ヽ(゚ )━ヽ(∀゚ )ノ━ヽ(゚∀゚)ノ━━!!!

キタ━━━ヽ(ヽ(゚ヽ(゚∀ヽ(゚∀゚ヽ(゚∀゚)ノ゚∀゚)ノ∀゚)ノ゚)ノ)ノ━━━!!!!

キタ━━━━━━(゚(゚∀(゚∀゚(゚∀゚)゚∀゚)∀゚)゚)━━━━━━ !!

キタ(゚∀゚)(゚∀゚)(゚∀゚)(゚∀゚)━━━━(゚∀゚)(゚∀゚)(゚∀゚)(゚∀゚)!!!!!

キタ━━━━━━\(゚∀゚)/━━━━━━ !!!!!

キタ*・゜゚・*:.。..。.:*・゜(゚∀゚)゚・*:.。. .。.:*・゜゚・*!!!!!

キタ━━(━(━(-( ( (゚∀゚) ) )-)━)━) ━━ !!!!!

キタ━━━━(Д゚(○=(゚∀゚)=○)Д゚)━━━━━!!

キタ━(Д゚(○=(Д゚(○=(Д゚(○=(゚∀゚)=○)Д゚)=○)Д゚)=○)Д゚)━!!!

キタ━━━ヽ( ゚∀゚)人(゚∀゚ )メ( ゚∀゚)人(゚∀゚ )メ( ゚∀゚)人(゚∀゚ )ノ━━━!!!!

AzureTableStorage(平均0.18秒)がSQLAzure(平均0.30秒)に勝った!

もう一度言います

AzureTableStorageはSQLAzureよりも高速!!!(直列100件登録の場合のみ)

生きててよかった・゚・(つД`)・゚・ 自分が生きてるうちにこんな日が来るとは、ずっとAzureTableStorageを愛し続けた甲斐がありました。

 

まとめ

  • 100件までであれば、SQLAzure/AzureTableStorageのパフォーマンスに差はない。
  • 万単位の大量データになってもサーバー/サービス側のパフォーマンスの差はそれほどないと思われる。クライアントライブラリの差がパフォーマンスに影響すると思われる。 「AzureTableStorageは遅い」は都市伝説です。
  • AzureTableStorageは遅くない、エンティティグループトランザクショントランザクションの件数の範囲(100件以内)であれば、SQLAzureよりも高速に動作することもある、トランザクション制御も可能

今回検証用に作成したソースはこちらからダウンロード可能です。「oretachinoAzureTableStorage_3.zip」をダウンロードしてみてください。

 

最後に検証プログラムを書き・実行してうまくいかなくて悶々としていた自分にいろいろとアドバイスをいただいた、@A_Ymさん、@statemachineさん、@normalianさんにお礼申し上げます。本当にありがとうございました。

Written by david9142

2011年10月26日 @ 9:55 PM

カテゴリー: WindowsAzure

Tagged with , ,

コメントを残す

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

WordPress.com ロゴ

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

Twitter 画像

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

Facebook の写真

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

Google+ フォト

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

%s と連携中

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