我如何初始化我的实体框架查询,以加快他们



我有一个登录页面,它执行一个非常简单的EF查询来确定用户是否有效。在第一次运行时,该查询大约需要6秒才能运行。在随后的运行中,它只需要不到一秒的时间。

我看过一篇关于使用应用程序自动启动的文章,我的问题是:是否有一种方法可以触发此查询以导致任何缓存需要发生,而无需实际调用查询,或者我是否有必要使用一组虚拟参数调用查询?

EDIT:当我说六秒时,我指的是获得查询所需的时间。代码看起来像这样(注意,在这种情况下,contactID是一个可空的int,并设置为null):

return from contact in _context.Contacts 
             where contact.District == Environment.District &&
             contact.ContactId == (contactID ?? contact.ContactId)
             select contact;

这是一个SqlServer 2008,我已经运行了一个分析器来检查SQL,它返回的持续时间是41毫秒,最终得到执行的查询。6或7秒的延迟发生在查询到达SQL之前。我现在试着设置瞥见,看看它是否能给我更多的细节,关于其他可能同时发生的事情。

这听起来确实像是所谓的"冷查询"。冷查询的主要性能瓶颈是"视图生成",它在应用程序的每个AppDomain中执行一次。典型的效果是,您的第一个查询(与哪个查询无关)很慢,而随后的查询很快。

不一定是一个可能很慢的查询。如果您在应用程序中使用EF执行的第一个操作是Insert,则会很慢。或者即使是根本不接触数据库的Attach也会很慢。(顺便说一下,这是一个很好的简单测试用例:在应用程序启动中添加一个context.Users.Attach(new User()),并在调试器中观察通过该行需要多长时间。)

在所有情况下,时间都被在内存中构建内部数据结构所消耗-本地查询"视图"(它们与数据库表视图无关)-每个AppDomain只发生一次。

视图生成在这里有更详细的描述,您还可以在这里找到如何在构建过程和部署之前"预生成"这些视图的资源。(注意:每次更改模型和重新部署应用程序时,您都必须更新这些预生成的内容。)

另一种方法是周期性地触发加载你的web应用程序的启动(例如通过一些进程访问站点)。在应用程序启动时,您将运行任何虚拟查询或上面的Attach东西或手动调用EF初始化:

using (var context = new MyContext())
{
    context.Database.Initialize(false);
}

编辑

我忘记了最后一个解决方案。忽略这6到7秒。如果您的站点很有名并且有合理的流量,那么这种冷查询就不太可能发生,因为IIS工作进程很少会关闭AppDomain。偶尔有用户在晚上访问这个网站,因为之前已经发生了这样的关闭,他们可能太累了,甚至没有注意到延迟。

相关内容

最新更新