2

设置:

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

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

任何关于为什么此操作可能会持续这么长时间的建议都值得赞赏。

更新 1

澄清一下 - 执行需要 40-60 秒的代码是(仅当数据库大小约为 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 毫秒(同时仍然给出相同的计数 - 8460)。因此,问题将是 - 数据库大小如何影响SaveChanges()

更新 2

运行性能分析器显示主要瓶颈(从“代码角度”来看)是以下方法:

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

此外,我必须说,在有问题的操作期间,该过程涉及的一张表大约有 400 万行(这张表有很多插入)。SQL Profiler 显示对该表的插入可以持续 1 到 200 毫秒(这是一个“峰值”)。再一次,这种变化似乎并没有重新重建案例索引。

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

4

1 回答 1

0

没有分析器很难猜测,但是 8000 条记录肯定太多了。通常 EF 4 最多可以处理数百个对象。如果更改跟踪花费了大部分时间,我不会感到惊讶。EF 5 和 6 有一些性能优化,所以如果你不能以某种方式减少被跟踪对象的数量,你可以尝试它们。

于 2013-03-19T15:12:05.230 回答