SaveChanges需要40到60秒才能保存~8000个上下文更改

时间:2013-03-19 14:46:34

标签: performance sql-server-2008 entity-framework

设定:

  • 启用了延迟加载的实体框架4(模型优先,每个层次的表)。
  • 表格数量约为40(并且没有表格超过15-20个字段)。
  • SQL Server Express 2008(不是r2)。
  • 没有数据库触发器或任何其他类似的东西存在 - 它仅用于存储。所有逻辑都在代码中。
  • 目前数据库大小约为2GB。
  • (主键是Guids,通过Guid.NewGuid()在代码中生成 - 如果这很重要)
  • 保存一个复杂的操作结果(产生一个复杂的对象图)需要40到60秒(SaveChanges返回的数字大约是8000 - 大多数是添加了对象而另一些是修改过的。)
  • 使用空(或几乎为空)数据库保存相同的操作结果通常需要在同一台计算机上大约1秒钟。

似乎影响此问题的唯一变量是数据库大小。但是请注意,我只是在测量Context.SaveChages()调用(所以即使我在某个地方有一些不应该影响这个问题的奇怪的缓慢查询)。

对于此操作可能持续这么长时间的任何建议都表示赞赏。

更新1

只是为了澄清 - 执行需要40-60秒的代码是(只有在DB大小约为2gb时才需要这么长时间):

Stopwatch sw = Stopwatch.StartNew();
int count = objectContext.SaveChanges(); // this method is not overridden
Debug.Write(sw.ElapsedMilliseconds); // prints out 40000 - 60000 ms
Debug.Write(count); // I am testing with exactly the same operation and the
                    // result always gives the same count for it (8460)

使用空DB的相同操作大约需要1000 ms(同时仍然给出相同的计数 - 8460)。因此问题是 - 数据库大小如何影响SaveChanges()

更新2

运行perf分析器显示主要瓶颈(来自“代码视角”)是以下方法:

Method:   static SNINativeMethodWrapper.SNIReadSync
Called:    3251 times
Avg:         10.56 ms
Max:        264.25 ms
Min:          0.01 ms
Total:    34338.51 ms

更新3

数据库中的所有PK和FK都有非聚集索引。我们使用随机Guids作为代理键(不是顺序),因此碎片总是处于非常高的水平。我尝试在重建所有数据库索引后立即测试执行有问题的操作(所有索引的碎片小于2-3%)但它似乎没有以任何方式改善这种情况。

此外,我必须说,在有问题的操作过程中,该过程中涉及的一个表大约有400万行(该表有很多插入)。 SQL事件探查器显示对该表的插入可以持续1到200毫秒(这是一个“尖峰”)。再一次,在案例索引新近重建的情况下似乎没有这种变化。

在任何情况下 - 似乎(目前)问题出现在应用程序的SQL Server端,因为占用时间的主要因素是SNIReadSync方法。如果我完全无知,请纠正我。

1 个答案:

答案 0 :(得分:0)

没有探查器很难猜测,但8000条记录肯定太多了。通常EF 4可以使用多达几百个对象。如果变化跟踪需要大部分时间,我不会感到惊讶。 EF 5和6有一些性能优化,所以如果你不能以某种方式减少跟踪对象的数量,你可以试验它们。