摘要:我们遇到了 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 的预发行书,但除了“编译您的查询”之外,我无法在其中找到任何帮助。
我不明白为什么需要 12-15 秒才能在 32 个表中生成单个选择,所以我很乐观,还有一些改进的余地!
感谢您的任何建议!我们在 SQL Server 2008 上运行以防万一,而 XP / 7 / server 2008 R2 使用 RTM VS2010。