0

今朝、一連のデータをテーブル ストレージに単純に挿入する簡単なクライアントを作成していたときに、その後の保存後にパフォーマンスが低下することに気付きました。

public class MyObject : TableServiceEntity
{
    public MyObject()
    {
        this.RowKey = Guid.NewGuid().ToString();
    }

    public string SomeProperty { get; set; }
}

そして、いくつかのデータを追加するための単純なコードのチャンクがあります....

Stopwatch timer = new Stopwatch();
            for (int i = 0; i < target / 50; i++)
            {
                CloudTableClient client = account.CreateCloudTableClient();
                client.CreateTableIfNotExist(entitySet);
                TableServiceContext context = client.GetDataServiceContext();

                timer.Reset();
                timer.Start();
                for (int x = 0; x < i * 50; x++)
                {
                    var obj = new MyObject();

                    context.AddObject(entitySet, obj);
                    context.SaveChanges();
                }
                total += 100;
                timer.Stop();

                Console.WriteLine("Added 100 entities in {0} seconds; total: {1}", timer.Elapsed.Seconds, total);
            }

そして、これが実行時に表示されるものです(コンソールアプリ)

Added 100 entities in 0 seconds; total: 100

Added 100 entities in 0 seconds; total: 200

Added 100 entities in 1 seconds; total: 300

Added 100 entities in 2 seconds; total: 400

Added 100 entities in 4 seconds; total: 500

Added 100 entities in 4 seconds; total: 600

Added 100 entities in 6 seconds; total: 700

Added 100 entities in 6 seconds; total: 800

パフォーマンスが低下するのはなぜですか?

  • コンテキスト、クライアント、および/またはアカウントをループの外に移動しても変化しません
  • context.ResolveTypeを実装しても問題は解決しませんでした
  • プロファイリング後、context.SaveChanges メソッドがボトルネックの場所です
  • アプリケーションを再実行すると、同じ結果が再現されます。データベースに数百/数千の他のエンティティがある場合でも。
4

1 に答える 1

1

この行のテストコードにはバグがあると思います。

for (int x = 0; x < i * 50; x++)

何度も繰り返しているi * 50ので、外側のループを通過するたびに、前回よりも50個多くのエンティティを追加します。初めて0エンティティを追加しますが、これは非常に高速です。次に50、次に100、次に150など。これは、実際に追加した数ではなくても、ロギングコードが毎回カウントに盲目的に100を追加するため、マスクされます。あなたがおそらく欲しかったのは:

for (int x = 0; x < 100; x++)

プロファイリングの結果に関しては、このコードのほとんどはメモリ内のデータで機能します。SaveChanges()ネットワーク呼び出しを行います。これが、費やされる時間を支配する理由です。

これはテストコードだと思います。ただし、実際に1つのPartitionKeyに多数のエンティティを追加しようとしている場合は、バッチを使用することをお勧めします。

于 2012-07-26T18:30:22.507 に答える