【问题标题】:Why does Performance Degrade with multiple calls to TableServiceContext.SaveChanges为什么多次调用 TableServiceContext.SaveChanges 会导致性能下降
【发布时间】:2012-07-27 02:30:22
【问题描述】:

今天早上我正在编写一个快速客户端,只是将一堆数据插入到表存储中,当我注意到后续保存后性能会下降。

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 方法是瓶颈所在
  • 重新运行应用程序会重现相同的结果;即使数据库中有成百上千的其他实体。

【问题讨论】:

    标签: azure azure-storage azure-table-storage


    【解决方案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() 进行网络调用,这就是它占主导地位的原因。

    我意识到这是测试代码。但是,如果您实际上尝试将大量实体添加到单个 PartitionKey 中,则建议使用批处理。

    【讨论】:

    • 谢谢!令人惊讶的是,忽略这一点是多么容易!
    猜你喜欢
    • 1970-01-01
    • 2016-12-24
    • 2013-10-15
    • 2012-04-17
    • 1970-01-01
    • 2013-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多