不,我的第二个问题的答案不是冬天。
前言
我最近一直在对Entity Framework进行大量研究,而且一直困扰着我的是它在查询没有预热时的性能,所谓的冷查询。
我浏览了Entity Framework 5.0的performance considerations文章。作者介绍了温暖和冷查询的概念以及它们之间的区别,我也注意到自己并不知道它们的存在。在这里,值得一提的是,我背后只有六个月的经验。
现在我知道如果我想在性能方面更好地理解框架,我还可以研究哪些主题。遗憾的是,互联网上的大部分信息都过时或过于主观,因此我无法找到有关 Warm vs Cold 查询主题的任何其他信息。
基本上我到目前为止注意到的是,每当我需要重新编译或回收点击时,我的初始查询变得非常慢。正如预期的那样,任何后续数据读取都很快(主观)。
我们将迁移到Windows Server 2012,IIS8和SQL Server 2012,作为一名少年,我实际上赢得了在其他人之前测试它们的机会。我很高兴他们推出了一个预热模块,可以让我的应用程序为第一个请求做好准备。但是,我不确定如何继续升温我的实体框架。
我所知道的是值得做的事:
我考虑做的是,通过常识,可能是错误的方法:
问题:
答案 0 :(得分:55)
您可以混合使用预生成视图和静态编译查询。
静态CompiledQuerys很好,因为它们可以快速轻松地编写并有助于提高性能。但是对于EF5,没有必要编译所有查询,因为EF将自动编译查询本身。唯一的问题是,当扫描缓存时,这些查询可能会丢失。因此,您仍然希望保留对自己编译的查询的引用,这些查询仅发生在非常罕见的情况下,但这些查询很昂贵。如果将这些查询放入静态类中,它们将在首次需要时进行编译。对于某些查询,这可能为时已晚,因此您可能希望在应用程序启动期间强制编译这些查询。
如您所述,预生成视图是另一种可能性。特别是,那些需要很长时间才能编译并且不会更改的查询。这样就可以将性能开销从运行时转移到编译时。这也不会引入任何滞后。但当然这种变化会传递到数据库,因此处理起来并不容易。代码更灵活。
不要使用大量的TPT继承(这是EF中的一般性能问题)。既不构建你的继承层次结构太深也不太宽。某些类特定的2-3个属性可能不足以要求自己的类型,但可以作为现有类型的可选(可空)属性处理。
长时间不要坚持单一的背景。每个上下文实例都有自己的第一级缓存,随着它越来越大,性能会降低。上下文创建很便宜,但是上下文的缓存实体内的状态管理可能变得昂贵。其他缓存(查询计划和元数据)在上下文之间共享,并将与AppDomain一起死亡。
总而言之,您应确保经常分配上下文并仅在短时间内使用它们,您可以快速启动应用程序,编译很少使用的查询,并为性能至关重要的查询提供预生成的视图。经常使用。
基本上,每次丢失AppDomain。 IIS每29 hours执行一次重新启动,因此您永远无法保证您的实例可以使用。此外,在没有活动的一段时间后,AppDomain也会关闭。你应该尝试再次快速上来。也许你可以异步进行一些初始化(但要注意多线程问题)。您可以使用在没有请求阻止AppDomain死亡的情况下在您的应用程序中调用虚拟页面的计划任务,但最终会这样做。
我还假设当您更改配置文件或更改程序集时,将重新启动。
答案 1 :(得分:8)
如果您希望在所有通话中获得最佳性能,请仔细考虑您的架构。例如,在应用程序加载时预先缓存服务器RAM中经常使用的查找而不是在每个请求上使用数据库调用可能是有意义的。该技术将确保常用数据的最小应用响应时间。但是,您必须确保具有良好的过期策略,或者在发生影响缓存数据的更改时始终清除缓存以避免并发问题。
通常,您应该努力设计分布式体系结构,以便在本地缓存的信息变得陈旧或需要事务时才需要基于IO的数据请求。任何“线上”数据请求通常需要比内存缓存检索中的本地检索长10-1000倍。与“本地与远程”数据问题相比,仅此一个事实常常使“冷与热数据”的讨论无关紧要。
答案 2 :(得分:7)
一般提示。
现在解释为什么虚拟请求不是错误的方法。
解释缓存何时“冷”。
这种情况发生在框架中应用缓存的任何层上,top of the performance page上有一个很好的描述。
您提到的其他内容,特别是重新编译和重新启动IIS,清除部分或全部内存缓存。
答案 3 :(得分:3)
正如您所说,使用“预先生成的视图”,这是您真正需要做的。
从link中提取: “当生成视图时,它们也会得到验证。从性能角度来看,视图生成的绝大部分成本实际上是视图的验证”
这意味着在构建模型装配时会发生性能爆震。然后,您的上下文对象将跳过“冷查询”,并在上下文对象生命周期的持续时间以及后续新对象上下文中保持响应。
执行不相关的查询除了消耗系统资源之外别无其他目的。
捷径......
答案 4 :(得分:2)
我没有这个框架的经验。但在其他情况下,例如Solr,完全虚拟读取将没有多大用处,除非你可以缓存整个数据库(或索引)。
更好的方法是记录查询,从日志中提取最常见的查询并使用它们进行预热。在继续之前,请确保不要记录热身查询或从日志中删除它们。