如何减少Entity Framework 4查询编译时间?

时间:2010-04-29 17:33:43

标签: .net entity-framework entity-framework-4

总结:我们遇到的问题是EF4查询编译时间超过12秒。缓存查询只会让我们到目前为止;我们有什么办法可以减少编译时间吗?有什么我们可能做错了我们可以寻找吗?谢谢!

我们有一个通过WCF服务公开的EF4模型。对于我们的每个实体类型,我们公开了一个方法来获取并返回整个实体以进行显示/编辑,包括许多引用的子对象。

对于一个特定的实体,我们必须.Include()31个表/子表来返回所有相关数据。不幸的是,这使得EF查询编译过于缓慢:编译和构建7,800行,300K查询需要12-15秒。这是Web UI的后端,需要比这更快。

我们可以做些什么来改善这个?我们可以CompiledQuery.Compile这个 - 在第一次使用之前没有做任何工作,所以有助于第二次和后续的执行,但我们的客户很紧张,第一次使用也不应该很慢。同样,如果托管Web服务的IIS应用程序池被回收,我们将失去缓存计划,尽管我们可以延长生命周期以最大限度地减少这种情况。此外,我无法提前预先编译此方法和/或序列化EF编译的查询缓存(缺少反射技巧)。 CompiledQuery对象只包含对缓存的GUID引用,因此它是我们真正关心的缓存。 (把它写出来对我来说,我可以在app_startup的后台开始执行所有查询来编译它们 - 这样安全吗?)

然而,即使我们确实解决了这个问题,我们也会根据我们正在搜索的参数动态地使用LINQ-to-Entities子句构建我们的搜索查询:我不认为SQL生成器做得足够好我们可以将所有逻辑移到SQL层中,所以我认为我们不能预先编译我们的搜索查询。这不太严重,因为搜索数据结果使用较少的表,因此只编译3-4秒而不是12-15,但客户认为最终用户仍然无法接受。

所以我们真的需要以某种方式减少查询编译时间。有什么想法吗?

  • 分析指向ELinqQueryState.GetExecutionPlan作为开始的地方,我试图进入,但没有真正的.NET 4源可用我不能走得太远,并且Reflector生成的源不会让我进入某些功能或在其中设置断点。
  • 该项目是从.NET 3.5升级的,所以我尝试在EF4中从头开始重新生成EDMX,以防它出现问题但没有帮助。
  • 我已经尝试过在这里宣传的EFProf实用程序,但它看起来不会对此有所帮助。无论如何,我的大型查询会崩溃其数据收集器。
  • 我已经通过SQL性能调优运行生成的查询,它已经有100%的索引使用率。我看不出会导致查询生成器问题的数据库有什么问题。
  • 执行计划编译器中是否存在O(n ^ 2) - 将其分解为单独数据加载的块而不是一次可能帮助的所有32个表?将EF设置为延迟加载没有帮助。
  • 我已经购买了预发布的O'Reilly Julie Lerman EF4书,但除了'编译你的查询'之外,我找不到任何帮助。

我不明白为什么在32个表格中生成一个选择需要12-15秒,所以我很乐观有一些改进的余地!

感谢您的任何建议!我们正在针对SQL Server 2008运行,如果重要,XP / 7 / server 2008 R2使用RTM VS2010。

5 个答案:

答案 0 :(得分:7)

让您的查询更简单。认真;查询复杂性和编译时间之间存在几乎线性的关系。两个简单查询通常比一个非常复杂的查询快得多(即使预编译!)。如果速度是最终目标,请选择最快的选项。

答案 1 :(得分:4)

您可以为一些更复杂的查询创建视图,从而完全控制SQL。然后在数据模型中包含该视图。

答案 2 :(得分:1)

这可能不是您正在寻找的答案,但是对于一个简单的解决方法,为什么不在webapp初始化(对webapp执行一些虚拟调用)而不是第一次运行时运行CompiledQuery.Compile(客户)电话。

答案 3 :(得分:1)

您可以尝试使用http://www.iis.net/download/ApplicationWarmup 它现在处于测试阶段,但我们也在考虑使用它。

答案 4 :(得分:1)

查看nqueries,它使用在应用程序启动期间生成的预编译查询。

编辑: 由于切换到EF5,NQueries在切换到DbContext时不再支持编译查询,如果您仍想查看,请使用1.03 release source code,它仍然是基于ObjectContext并支持编译查询。