如何“热身”实体框架?什么时候变“冷”?


118

不,我第二个问题的答案不是冬天。

前言:

最近,我对Entity Framework进行了大量研究,而令我困扰的是当查询未预热时的性能,即所谓的冷查询。

我浏览了有关Entity Framework 5.0 的性能注意事项的文章。作者介绍了“ 热”和“ 冷”查询的概念以及它们之间的区别,我也注意到自己而并不知道它们的存在。在这里可能值得一提的是,我只有六个月的经验。

现在,我知道如果我想从性能方面更好地理解框架,我可以进一步研究哪些主题。不幸的是,Internet上的大多数信息已经过时或过分带有主观性,因此,我无法找到有关“ 冷”查询主题的任何其他信息。

到目前为止,基本上我注意到的是,每当我需要重新编译或回收利用命中时,我的初始查询就会变得非常缓慢。如预期的那样,任何后续数据读取都是快速的(主观的)。

我们将迁移到Windows Server 2012,IIS8和SQL Server 2012,作为一名初中生,我实际上赢得了自己在其余测试之前进行测试的机会。我很高兴他们引入了一个预热模块,该模块可以使我的应用程序为第一个请求做好准备。但是,我不确定如何继续预热我的实体框架。

我已经知道值得做的事情:

  • 根据建议提前生成我的视图。
  • 最终将我的模型移到单独的装配中。

按照常识,我考虑做的可能是错误的方法

  • 在应用程序启动时读取虚拟数据,以进行预热,生成和验证模型。

问题:

  • 何时在我的实体框架上实现高可用性的最佳方法是什么?
  • 在什么情况下,实体框架会再次“变冷”?(重新编译,回收,IIS重新启动等)

找出是最受您欢迎的是视图生成还是查询编译。如果这是view gen,则使用预编译的视图。如果这是查询-您是否拥有复杂的层次结构?请注意,昂贵的事情通常每个应用程序域发生一次并被缓存,因此,当卸载应用程序域并创建新的应用程序域时,您会看到这种问题。
Pawel 2012年

我已经提到了视图生成@Pawel,层次结构并不复杂,甚至一点也不复杂。但是问题也是主要的。按照您所说的,我将研究何时卸载应用程序域。但是,如果像您所说的那样卸载应用程序域,那仍然无法解决另一个使Entity Framework升温的问题。在这一点上,似乎应用程序域正在卸载超过它应该是,我不知道为什么,回收只在夜间,怠速设置为0
彼得

4
您为什么认为进行虚拟数据读取是错误的方法?
Josh Heitzman '11

5
只是感觉不对,我以为可能有些更优雅的东西我没意识到。但是,如果那是唯一的解决方案,并且拥有丰富知识的人可以确认没有其他方法,那么我将继续解决。
彼得

1
在一段时间不活动之后(由于流量较低),应用程序池关闭时遇到的一个问题是创建一个服务,该服务在设定的时间间隔内向您的页面之一发出请求。这样可以避免在第一个请求重新启动应用程序池之前的长时间延迟。或者,您可以使用www.pingalive.com之类的免费服务来ping您的域名/ ip。这也有助于防止缓存的对象在过期之前被清除。
hatsrumandcode 2013年

Answers:


55
  • 何时在我的实体框架上实现高可用性的最佳方法是什么?

您可以混合使用预生成的视图和静态编译的查询。

静态CompiledQuerys很好,因为它们编写起来快速简便,并有助于提高性能。但是,使用EF5无需编译所有查询,因为EF会自动编译查询本身。唯一的问题是,在清除高速缓存时,这些查询可能会丢失。因此,对于那些很少发生但很昂贵的查询,您仍然希望保留对自己的已编译查询的引用。如果将这些查询放入静态类,则会在首次需要它们时对其进行编译。对于某些查询来说可能为时已晚,因此您可能需要在应用程序启动期间强制编译这些查询。

正如您提到的,预生成视图是另一种可能性。特别是对于那些需要很长时间才能编译且不会更改的查询。这样,您可以将性能开销从运行时转移到编译时。同样,这不会带来任何滞后。但是,当然,此更改会传递到数据库,因此处理起来并不容易。代码更加灵活。

不要使用太多的TPT继承(这是EF中的一般性能问题)。建立继承层次结构的深度和宽度都不要太深。仅特定于某个类的2-3个属性可能不足以需要自己的类型,但是可以将其作为现有类型的可选(可空)属性来处理。

不要长时间保持单一上下文。每个上下文实例都有自己的一级缓存,随着它的增大,它会降低性能。上下文创建很便宜,但是上下文的缓存实体内部的状态管理可能会变得很昂贵。其他缓存(查询计划和元数据)在上下文之间共享,并将与AppDomain一起消失。

总而言之,您应该确保频繁分配上下文并仅在短时间内使用它们,以便可以快速启动应用程序,编译很少使用的查询,并为性能关键且经常使用的查询提供预生成的视图。

  • 在什么情况下,实体框架会再次“变冷”?(重新编译,回收,IIS重新启动等)

基本上,每次您丢失AppDomain时。IIS每29小时执行一次重新启动,因此您永远不能保证实例会存在。同样,经过一段时间没有活动后,AppDomain也将关闭。您应该尝试再次快速出现。也许您可以异步进行一些初始化(但是要注意多线程问题)。您可以使用计划的任务在没有请求防止AppDomain死亡的情况下调用应用程序中的伪页面,但最终会失败。

我还假设当您更改配置文件或更改程序集时,将要重新启动。


谢谢安德烈,那是我所需要的。
彼得

@Andreas实际上,即使使用静态编译查询,第一次运行的时间仍然太长。除了以下以外,还有什么方法可以进行预热:在应用程序启动时读取虚拟数据以预热,生成和验证模型。
manishKungwani

@Andreas那么实体framework5是否需要它?如果在ef5上使用它有什么不同(我是说还是慢或连击还是没什么不同?)
qakmak 2014年

“静态CompiledQuerys很好,因为它们编写起来容易快捷,并有助于降低性能。” 性能降低?
Mathemats

9

如果您希望在所有通话中获得最佳性能,则应仔细考虑您的体系结构。例如,当应用程序加载时,将经常使用的查询预缓存在服务器RAM中可能是有意义的,而不是在每个请求上都使用数据库调用。该技术将确保对常用数据的最小应用程序响应时间。但是,您必须确保具有行为良好的过期策略,或者在进行任何会影响缓存数据的更改时始终清除缓存,以避免并发问题。

通常,您应该努力设计分布式体系结构,以便仅在本地缓存的信息过时或需要进行事务处理时才需要基于IO的数据请求。在内存缓存检索中,任何“在线”数据请求的检索时间通常比本地检索时间长10-1000倍。仅凭这一事实,与“本地与远程”数据问题相比,有关“冷数据与热数据”的讨论就显得无关紧要了。


当我大肆宣传实体框架原始性能时,这是我经常忽略的一个好点。我将对此进行进一步研究,并进一步研究缓存原理。但是,我仍然想更好地理解EF方面的“冷与暖”。
彼得

2
“仅凭这一事实,与“本地与远程”数据问题相比,有关“冷数据与热数据”的讨论就显得无关紧要了。” 并不是的。如果您没有在本地缓存它(最初不会这样做),您仍然需要打EF并遭受初始化痛苦,以便准备缓存。在未初始化缓存的相同位置,EF也将被初始化。因此,如果唯一的问题是EF初始化时间,则添加一层缓存可能无济于事,但这会增加另一层复杂性……
MikeJansen 2014年

8

一般提示。

  • 执行严格的日志记录,包括访问内容请求时间
  • 初始化应用程序以热启动从上一步拾取的非常慢的请求时,请执行虚拟请求。
  • 除非存在实际问题,否则不要费心进行优化,与应用程序的使用者进行交流并提出要求。如果只是想找出需要优化的内容,就可以轻松拥有一个连续的反馈循环。

现在来解释为什么虚拟请求不是错误的方法

  • 降低复杂性 -您以一种可以在不更改框架的情况下正常工作的方式对应用程序进行热身,并且无需弄清楚可能的时髦API /框架内部结构,就可以正确地进行操作
  • 更大的覆盖范围 -您正在立即对与缓慢请求有关的所有缓存层进行预热。

解释高速缓存何时“冷”。

这种情况发生在您框架中应用缓存的任何层,性能页顶部有一个很好的描述。

  • 在可能使缓存失效的潜在更改之后,当必须验证缓存时,这可能是超时或更智能的(即,缓存项的更改)。
  • 逐出缓存项时,链接的性能文章中的“缓存逐出算法”部分对此进行了描述,但总而言之。
    • LFRU(最不常用-最近使用)缓存命中次数和年龄,限制为800个项目。

您提到的其他内容(特别是重新编译和重新启动IIS)会清除部分或全部内存缓存。


这是另一个有用的答案,非常感谢。
彼得

3

如您所说,使用“预生成视图”实际上就是您需要做的所有事情。

从您的链接中摘录:“生成视图时,也会对其进行验证。从性能的角度来看,视图生成的绝大部分成本实际上是对视图的验证”

这意味着在构建模型装配时会发生性能下降。然后,您的上下文对象将跳过“冷查询”,并在上下文对象生命周期以及后续新对象上下文的持续时间内保持响应。

执行无关的查询只会消耗系统资源,而没有其他目的。

快捷方式...

  1. 跳过所有预生成视图的额外工作
  2. 创建对象上下文
  3. 触发那个甜蜜无关的查询
  4. 然后,只需在过程中保留对对象上下文的引用即可(不推荐)。


2

我没有这个框架的经验。但是在其他情况下,例如Solr,除非您可以缓存整个数据库(或索引),否则完全虚拟读取将无用。

更好的方法是记录查询,从日志中提取最常见的查询,然后使用它们进行预热。只需确保不要记录预热查询或在继续操作之前将其从日志中删除。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.