使用TPH&时LINQ to Entities的初始性能问题复杂的类型,Pregen Views似乎什么都不做?

时间:2014-11-28 13:20:20

标签: entity-framework linq-to-entities entity-framework-5 entity-framework-6

我正在使用MVC3,ASP.NET 4.5,LINQ to Entities,EF5和SQL Server 2008 R2以及Azure(用于实时)。

我在单独的模型项目中为模型创建csdl,edml,msl和ssdl文件。

这些文件由Devart的Entity开发人员制作,我在那里管理我的实体模型。

目标:实体框架5

  • 延迟加载:已启用
  • 查看生成:真实
  • 构建验证: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秒才能完成。连续运行大约需要200ms。

当我使用ORM Profiler进一步分析时,它给出了LINQ代码:

Cat.MergeAs(0).Any(a => a.OwnerId == ((Nullable<int>)myOwnerId))

我在Related SO Question发现了一个很棒的问题,但它不够深入。虽然它建议升级到EF6,但它没有提到新的EF6问题,因为它现在是.NET运行时的外部,因此必须在首次使用时JIT EF运行时。也许在更高版本的EF6即6.1.2中,这已经解决了。

一旦EF创建了T-SQL,它就会非常快速地运行。我在SSMS中对此进行了测试。

所以我的问题,截至2014年11月,由以下内容组成:

1)如何尝试预生成的视图,我如何解决TPH /复杂类型场景的初始加载延迟。我见过对“编译查询”的引用。

2)也许我应该升级到EF6?但是,如果我这样做,现在EF运行时本身会有JIT惩罚,我应该如何解决这个问题。我部署到Azure网站。

3)最后我发现其他更简单的查询得益于预生成的视图,因此我正在使用它们。它仅适用于此TPH /复杂类型场景,它没有任何影响。是否存在pregen视图没有影响的情况?

4)3)可能是由于EF5现在可以“自动编译查询”所花费的时间。已经预先生成了View,我想这是下一个瓶颈。也许像我这样的复杂实体的这种“自动编译”功能需要很长时间,因此可以进行主动手动编译吗? Quess这就是所谓的“CompiledQuery”。是否与编写这些额外的代码相关,或者EF6x会帮助我吗?我有一个强烈的预感,这个查询编译步骤是瓶颈,但也意识到编写编译查询也不一定是最容易和可维护的解决方案。目前我们有一个定期启动工作,只是预热所有这些复杂的实体,因此用户直接进入“热查询执行模式”。

对此有任何帮助将非常感激。

EDIT1

我刚刚使用了JetBrains的DotTrace配置文件更深入,它似乎证实了我的瓶颈正在发生:

System.Data.Query.PlanCompiler.PreProcessor.Process(Dictionary[EdmFunctionEdmProperty[]]&)

首次点击时,它在此处花费了99%的时间,这证实了我的观点,即它与查询计划生成有关。我如何解决这个问题是另一回事。

EDIT2

我将在听完一些好的建议后测试EF 6.1.2并跟随Julie Lerman关于Pluralsight的优秀课程。

1 个答案:

答案 0 :(得分: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提供程序。