【发布时间】:2010-04-29 17:33:43
【问题描述】:
总结:我们遇到了 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 秒,但客户认为最终用户仍然无法接受。
所以我们确实需要以某种方式减少查询编译时间。有什么想法吗?
- Profiling 指向 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。
【问题讨论】:
-
我们也有这个问题,这是一个大问题。执行查询的时间最多为 2-300 毫秒,而等待 ELinqQueryState.GetExecutionPlan() 需要 8-9 秒。那是在将 EF 无法处理的大型急切负载查询(过去每个 qry 需要 2-4 分钟等待 ELinqQueryState.GetExecutionPlan())拆分为许多更简单的急切负载查询之后。我想我们能做的就是等待 EF5,它应该可以减轻由此造成的一些痛苦。
-
我已经在 msdn.forums 上发布了关于这个问题的帖子,希望能得到一些指导,在这里social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/…
-
@Mahol25 谢谢 - 我会看那个帖子。很抱歉,在我离开项目之前,我们从来没有把我们的查询降到不到一秒钟,所以除了已经在这里的内容之外,我没有任何具体的建议可以给你。
标签: .net entity-framework entity-framework-4