どう使う? windows azure テーブル

21
どどどどWindows Azure どどどど SQL Azure ににに にに にに (Akihiro Yamamoto) Twitter : A_Ym

Upload: akihiroyamamoto

Post on 26-Jun-2015

1.509 views

Category:

Technology


0 download

DESCRIPTION

Windows Azure Table Storage parallel processing code tips.

TRANSCRIPT

Page 1: どう使う? Windows azure テーブル

どう使う? Windows Azure テーブル

~ SQL Azure に挑む ~山本 昭宏 (Akihiro Yamamoto)

Twitter : A_Ym

Page 2: どう使う? Windows azure テーブル

プロフィール

Microsoft 系テクノロジーコンサルタント会社勤務– 興味のあるテクノロジー

Windows Azure, C# 4, LINQ, WPF, WCF, WF, Silverlight Software Factories

Windows Azure の活動– Windows Azure Community

トレーニングキットの翻訳や技術検証、情報の整理をしていました。

– Web メディア @IT 「 Windows Azure Platform 速習シリーズ: SQL Azure -

SQL Azure の機能と制約を理解する」 の記事を執筆させていただきました。

– セミナー Tech Days 2010 「 Windows Azure Platform 徹底検証」 に

て技術検証を行い、スピーカーとして登壇させていただきました。

Page 3: どう使う? Windows azure テーブル

テーブル ストレージのスペックおさらい

Page 4: どう使う? Windows azure テーブル

トランザクションスペック (Windows Azure Storage Team Blog より )

1 entity 追加 = 1 トランザクション 100 entity に対する変更の反映 ( エンティティ グ

ループ トランザクション ⇒ EGT を使用しない場合 )

= 100 トランザクション 100 entity に対する変更の反映

(EGT を使用する場合 ) = 1 トランザクション PartitionKey と RowKey が一致した場合のクエ

リ = 1 トランザクション

1 クエリ で 500 entity 返された場合 (継続トークンが発生しない場合) = 1 トランザクション

1 クエリで 5 リクエスト 発生した場合 ( 4 つの継続トークンが発生した場合) = 5 トランザクション

Page 5: どう使う? Windows azure テーブル

パフォーマンススペック (Windows Azure Storage Team Blog より )

1 パーティションあたりのパフォーマンス– 最大 500 トランザクション / sec

極力パーティションが均等に分散するような設計によりパフォーマンスが向上する

理論値 ?– 参照 500 entity × 500 トランザクション = 250,000

entity / sec– 追加 100 entity × 500 トランザクション = 50,000

entity / sec

Page 6: どう使う? Windows azure テーブル

出ませんでした。

Page 7: どう使う? Windows azure テーブル

並列処理実装方法

Page 8: どう使う? Windows azure テーブル

追加の並列処理 (1/3)

var contexts = new TestTableContext[10000];

Parallel.For(0, contexts.Count(),(idx) =>{    contexts[idx] = EntityController.CreateTestTableContext();

    contexts[idx].SaveChangesDefaultOptions =   SaveChangesOptions.ContinueOnError | SaveChangesOptions.ReplaceOnUpdate ;}

Int64 from = 0;Int64 to   = 1000000;

int counter    = 0;int parallelUnit = 100;

using(var manualEvent = new ManualResetEvent(false)){    for (Int64 rowIdx = from; rowIdx < to; rowIdx++) { var entity =         new TestTableEntity()            {                  PartitionKey = ((Int64)(Math.Floor((double)rowIdx / 1000))).ToString("0000000000")                , RowKey       = rowIdx.ToString("0000000000")                , Id           = rowIdx                , Text         = "Text_" + rowIdx.ToString("0000000000")            };

        var context = contexts[(int)Math.Floor((double)rowIdx / to * contexts.Count())];

        context.AddTestTableEntity(entity);

使用法

1. 追加に使用する TableServiceContext を生成します。EGT のトランザクション単位は 100 entity に制限されていますので、 1000,000 entity 追加する場合は 10,000 の TableServiceContext を使用します。

2. ManualResetEvent を並列処理の同期に使用します。

Page 9: どう使う? Windows azure テーブル

追加の並列処理 (2/3)

    if (rowIdx % parallelUnit == parallelUnit - 1 || rowIdx == to - 1)        {            context.SaveChangesAsParallel(             (exception) =>                {                    if (exception != null)                    {

                    }

                 if (Interlocked.Increment(ref counter) >= (int)(to / parallelUnit))                 {                     manualEvent.Set();                 }                }                );        } }

manualEvent.WaitOne();}

使用法 (つづき)

6. EGT 単位で追加完了時にカウンターを同期インクリメントし、全件追加が完了したらメインスレッドの待機状態を解除します。

3. EGT 単位 (100 entity) で非同期追加処理を行います。

4. メインスレッドを待機状態にします。

5. 例外発生時の処理を行います。

Page 10: どう使う? Windows azure テーブル

追加の並列処理 (3/3)public static IAsyncResult SaveChangesAsParallel( this TableServiceContext context , Action<Exception> completeAction){    var asyncCallback =        new AsyncCallback(         (asyncResult) =>         {             DataServiceResponse response;

             try             {                 response = context.EndSaveChanges(asyncResult);

              completeAction(null);             }             catch (Exception exception)             {

             }         }            );

    var ret =   context.BeginSaveChanges(             SaveChangesOptions.Batch         , asyncCallback            , null            );

    return ret;}

TableServiceContext.BeginSaveChanges メソッドの第1 パラメーターに SaveChangesOptions.Batch オプションを指定して EGT 追加処理を行います。

Page 11: どう使う? Windows azure テーブル

クエリの並列処理 (1/3)

IEnumerable<Expression<Func<TestTableEntity, bool>>> GetWhereExpressions(){    for (int pIdx = 0; pIdx <= 999; pIdx++)    {        yield return (TestTableEntity entity) => entity.PartitionKey == pIdx.ToString("0000000000");    }}

var context = EntityController.CreateTestTableContext();

var query =    from        entity in context.TestTableEntity    select        entity    ;

var entities = query.QueryAsParallel<TestTableEntity>( GetWhereExpressions(), null);

使用法

where に使用する式は yield return で返します。これを使用しないと列挙の最後の式しか処理されません。

Page 12: どう使う? Windows azure テーブル

クエリの並列処理 (2/3)public static IEnumerable<TEntity> QueryAsParallel<TEntity>(      this IQueryable<TEntity> query    , IEnumerable<Expression<Func<TEntity, bool>>> whereExpressions    ) {    int whereExpressionsCount = whereExpressions.Count();

    var entities = new List<TEntity>();    var syncRoot = (entities as ICollection).SyncRoot;

    using (var manualResetEvent = new ManualResetEvent(false))    {        ThreadPool.RegisterWaitForSingleObject(              manualResetEvent            , new WaitOrTimerCallback( (_state, timeout) => { manualResetEvent.Set(); } )            , null            , 300000            , false            );

        foreach (var whereExpression in whereExpressions)        {            var dataServiceQuery = (DataServiceQuery<TEntity>) query.Where(whereExpression);

            var asyncCallback =                new AsyncCallback(                    (asyncResult) =>                    {                        try                        {                            var response = dataServiceQuery.EndExecute(asyncResult);

                            lock (syncRoot) { entities.AddRange(response.ToArray()); }                        } catch (Exception exception)                        {                                                    }

2. タイムアウトの設定を行います。

3. Select 式と Wehere 式を組み合わせてクエリを作ります。

5. 結果を lock で同期してリストに追加します。 (4. は次ページ )

6. 例外を処理します。

1. ManualResetEvent を並列処理の同期に使用します。

Page 13: どう使う? Windows azure テーブル

クエリの並列処理 (3/3)                        finally                        {                            if (Interlocked.Decrement(ref whereExpressionsCount) == 0)                            {                                manualResetEvent.Set();                            }                        }                    }                    )                    ;

                    dataServiceQuery.BeginExecute(asyncCallback, null);                }

                manualResetEvent.WaitOne();            }

            return entities;        }

7. 全てのクエリが完了したらメイン スレッドの待機状態を解除します。

4. メイン スレッドを待機状態にします。

Page 14: どう使う? Windows azure テーブル

テーブル サービス エンティティの基本形[DataContract][DataServiceKey("PartitionKey", "RowKey")]public class TestTableEntity{    public TestTableEntity()    {    }

    [DataMember]    public string PartitionKey { get; set; }

    [DataMember]    public string RowKey { get; set; }

    [DataMember]    public DateTime Timestamp { get; set; }

    [DataMember]    public string TypeAssemblyQualifiedName { get; set; }

    public string ETag    {        get;        private set;    }

    public void SetETag(string etag)    {        ETag = etag;    }

    [DataMember]    public Int64 Id { get; set; }

    [DataMember]    public string Text { get; set; }}

テーブル サービス エンティティとして必須のプロパティを用意します。

CLR にマッピングするためのキーを格納するプロパティを用意します。

Etag を保持するプロパティと設定するメソッドを用意します。(テーブル格納対象外)

WCF の データコントラクトとして使用できないので TableServiceEntity クラスは継承せずに、 DataServiceKey 属性を設定します。

Page 15: どう使う? Windows azure テーブル

継続トークン処理の拡張メソッド化 (1/2)

var context = EntityController.CreateTestTableContext();

var query =    from        entity in context.TestTableEntity    select        entity    ;

var entities = query.QueryContinuously();

使用法

Page 16: どう使う? Windows azure テーブル

継続トークン処理の拡張メソッド化 (2/2)public static IEnumerable<TEntity> QueryContinuously<TEntity>(this IQueryable<TEntity> query){    var resultList = new List<TEntity>();

    string nextPartitionKey = null;    string nextRowKey       = null;

    do {        var dataServiceQuery = query as DataServiceQuery<TEntity>;

        if (dataServiceQuery == null) { break; }

        if (nextPartitionKey != null) {            dataServiceQuery = dataServiceQuery.AddQueryOption("NextPartitionKey", nextPartitionKey);

            if (nextRowKey != null) {                dataServiceQuery = dataServiceQuery.AddQueryOption("NextRowKey", nextRowKey); }        }

        var result   = dataServiceQuery.Execute();        var response = result as QueryOperationResponse;

        resultList.AddRange(result);

        nextPartitionKey = null;        nextRowKey       = null;

        response.Headers.TryGetValue("x-ms-continuation-NextPartitionKey", out nextPartitionKey);        response.Headers.TryGetValue("x-ms-continuation-NextRowKey"      , out nextRowKey);    }    while (nextPartitionKey != null);

    return resultList;}

Page 17: どう使う? Windows azure テーブル

まとめ

Page 18: どう使う? Windows azure テーブル

Windows Azure テーブル vs. SQL Azure

並列処理を行えばパフォーマンスで SQL Azure に迫ることができます。

追加処理ではエンティティ グループ トランザクション (EGT) を組み合わせるとスループットが向上し、場合によっては SQL Azure を上回ります。

膨大なデータに対し、インスタンスサイズを大きくしたり、インスタンス数を増やすことによりリニアに対応できます。

ただし、 PartitionKey の設計や並列処理の実装、メンテナンスのコストを考えると SQL Azure で対応可能なことを無理にテーブルで実現するメリットは小さいと言えます。

数 10GB 以上のデータを扱うケースで有効だと考えます。⇒ 現在のところ Dallas との連携が有望だとみています。

Page 19: どう使う? Windows azure テーブル

参考情報 (1/2)

Web メディア– Windows Azure Storage Team Blog

Understanding Windows Azure Storage Billing – Bandwidth, Transactions, and Capacity(http://blogs.msdn.com/b/windowsazurestorage/archive/2010/07/09/understanding-windows-azure-storage-billing-bandwidth-transactions-and-capacity.aspx)

Windows Azure Storage Abstractions and their Scalability Targets(http://blogs.msdn.com/b/windowsazurestorage/archive/2010/05/10/windows-azure-storage-abstractions-and-their-scalability-targets.aspx)

– @IT 「 Windows Azure ストレージ開発入門(前編) - 初めての

Windows Azure テーブル・ストレージ開発」(http://www.atmarkit.co.jp/fdotnet/dnfuture/winazurestorage_01/winazurestorage_01_01.html)

Page 20: どう使う? Windows azure テーブル

参考情報 (2/2)

Windows Azure ベンチマーク サイト– Azurescope: Benchmarking and Guidance for Windows

Azure http://azurescope.cloudapp.net/

書籍 (並列処理関連)– More Effective C# ( 翔泳社 )– .NET のクラスライブラリ設計 (日経 BP ソフトプレス)– 究極の C# プログラミング (技術評論社)

Page 21: どう使う? Windows azure テーブル

おわりご静聴ありがとうございました。