使用 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”。

LINQ TO SQL 和 ADO.NET ENTITY 有啥区别呢?

EF6 - 使用可为空属性(外键,TPH)时的无效 SQL 查询