使用 TPH 和复杂类型时 LINQ to Entities 的初始性能问题,Pregen 视图似乎啥都不做?
Posted
技术标签:
【中文标题】使用 TPH 和复杂类型时 LINQ to Entities 的初始性能问题,Pregen 视图似乎啥都不做?【英文标题】:Initial performance issue with LINQ to Entities when using TPH & complex types, Pregen Views seem to do nothing?使用 TPH 和复杂类型时 LINQ to Entities 的初始性能问题,Pregen 视图似乎什么都不做? 【发布时间】:2015-01-27 04:02:53 【问题描述】:我正在使用 MVC3、ASP.NET 4.5、LINQ to Entities、EF5 和 SQL Server 2008 R2 以及 Azure(实时)。
我正在为单独的模型项目中的模型创建 csdl、edml、msl 和 ssdl 文件。
这些文件由来自 Devart 的实体开发人员生成,我在那里管理我的实体模型。
目标:实体框架 5
延迟加载:已启用 视图生成:True 构建时验证:True 元数据工件处理:嵌入输出程序集 使用了ObjectContext ObjectContext 代理创建已启用:true。我在我的实体模型中实现了 TPH 继承,其中子类也由多达 10 个复杂类型 (CTn) 组成。
Animal<-Cat(CT1,CT2,CT3 etc) (for example)
每个复杂类型都映射到通用动物表中的列。
我的初始 LINQ 是:
if (db.Animal.OfType<Cat>().Any(a => a.OwnerId == myOwnerId))
首次运行时,可能需要大约 40 秒才能完成。连续运行大约需要 200 毫秒。
当我使用 ORM Profiler 进一步分析时,它给了我 LINQ 代码:
Cat.MergeAs(0).Any(a => a.OwnerId == ((Nullable<int>)myOwnerId))
我在Related SO Question 发现了一个很棒的 SO 问题,但它还不够深入。虽然它建议升级到 EF6,但它没有提到新的 EF6 问题,即在首次使用时必须 JIT EF 运行时,因为它现在在 .NET 运行时之外。也许在更高版本的 EF6 即 6.1.2 中解决了这个问题。
一旦 T-SQL 由 EF 创建,它就可以非常快速地运行。我已经在 SSMS 中对此进行了测试。
因此,截至 2014 年 11 月,我的问题包括:
1) 我如何解决我的 TPH/复杂类型场景的初始加载延迟,已尝试预生成的视图。我看到了对“编译查询”的引用。
2) 也许我应该升级到 EF6?但是,如果我这样做了,现在是否对 EF 运行时本身有 JIT 惩罚,我应该如何解决这个问题。我部署到 Azure 网站。
3) 最后我发现其他更直接的查询受益于预生成的视图,所以我正在使用它们。只是对于这种 TPH/Complex Type 场景,它没有影响。是否存在 pregen 视图没有影响的情况?
4) 可能 3) 是由于 EF5 现在可以执行的“自动编译查询”所花费的时间。预先生成视图后,我想这是下一个瓶颈。也许像我这样的复杂实体的这种“自动编译”功能需要很长时间,所以可以进行主动手动编译吗? Quess 这就是所谓的“CompiledQuery”。编写这个额外的代码是否相关,或者 EF6x 会在这里帮助我吗?我有一种强烈的预感,这个查询编译步骤是瓶颈,但我也意识到编写编译查询也不一定是最容易和可维护的解决方案。目前我们有一个周期性的启动作业,它只是预热所有这些复杂的实体,所以用户直接进入“暖查询执行模式”。
任何有关上述内容的帮助将不胜感激。
编辑1
我刚刚使用了 JetBrains 的 DotTrace Profile,它更深入,它似乎证实了我的瓶颈正在发生:
System.Data.Query.PlanCompiler.PreProcessor.Process(Dictionary[EdmFunctionEdmProperty[]]&)
在第一次命中时,它 99% 的时间都花在这里,这证实了我的观点,即它与查询计划生成有关。我如何解决这个问题是另一回事。
EDIT2
在获得一些好的建议并遵循 Julie Lerman 的 Pluralsight 优秀课程后,我将在 EF 6.1.2 上进行测试。
【问题讨论】:
【参考方案1】:我遇到了类似的问题,并尝试了多种方法来提高“首次命中”性能。
您是否考虑过实现 IProcessHostPreloadClient
来预热缓存并通过实体框架模型对数据库进行初始调用?
这个解决方案对我有用,我在下面创建了一个示例 PreWarmCache 类:
namespace MyNamespace
public class PreWarmCache : IProcessHostPreloadClient
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
private readonly SystemRepository _systemRepository = new SystemRepository();
public void Preload(string[] parameters)
// Perform initialization and cache loading logic
Logger.Debug("Application Started: 0", _systemRepository.InitAppliation() ? "DB response OK" : "DB response failed");
查看this blog 了解如何将其连接到 IIS 上的 AutoStart 提供程序的详细信息。
【讨论】:
感谢您。我会试试这个。我确实运行了一个由 Pingdom 调用的预热序列,以确保该对象保持热状态。不理想,但它可以完成工作。以上是关于使用 TPH 和复杂类型时 LINQ to Entities 的初始性能问题,Pregen 视图似乎啥都不做?的主要内容,如果未能解决你的问题,请参考以下文章
无法在 linq to entity 查询中构造实体或复杂类型“x”
在 LINQ to Entities 查询中无法构造实体或复杂类型
在 LINQ to Entities 查询中无法构造实体或复杂类型
在 LINQ to Entities 查询中无法构造实体或复杂类型“Cits.Data.LineImg”。