我有一个登录页面,它执行一个非常简单的EF查询来确定用户是否有效。在第一次运行时,此查询大约需要6秒才能运行。在后续运行中,它需要不到一秒钟。
我看过一篇讨论使用Application Auto-Start的文章,我的问题是这样的:有没有办法触发此查询以在不实际调用查询的情况下导致任何缓存需要,或者是否有必要对我来说,用一组虚拟参数调用查询?
编辑:当我说六秒时,我指的是获取查询所需的时间。代码看起来像这样(注意,在这种情况下,contactID是一个可以为null的int并设置为null):
return from contact in _context.Contacts
where contact.District == Environment.District &&
contact.ContactId == (contactID ?? contact.ContactId)
select contact;
这是一个SqlServer 2008,我运行一个分析器来检查SQL,它返回的持续时间是41ms,最终执行的查询。 6或7秒延迟发生在查询甚至到达SQL之前。我现在正试图瞥见它是否可以给我更多关于可能同时发生的其他事情的细节。
答案 0 :(得分:2)
这听起来像是所谓的“冷查询”。冷查询的主要性能botteneck是“View Generation”,每个应用程序的AppDomain执行一次。通常情况下,您的第一个查询 - 无论哪个查询 - 都很慢,后续查询速度很快。
它一定不一定是一个可能很慢的查询。如果您在应用程序中使用EF进行的第一个操作是插入速度很慢。或者甚至根本不接触数据库的Attach
也会很慢。 (顺便说一下,这是一个很好的简单测试用例:在应用程序启动时添加context.Users.Attach(new User())
,并在调试器中查看通过该行所需的时间。)
在所有情况下,通过在内存中构建内部数据结构来消耗时间 - 本地查询“视图”(它们与数据库表视图无关) - 每个AppDomain发生一次。
视图生成更详细地描述了here和here,您还可以在其中找到资源,如何在构建过程中和部署之前“预生成”这些视图。 (注意:每次更改模型并重新部署应用程序时,都必须更新这些预生成。)
另一种方法是定期触发加载您的Web应用程序(通过某些进程,例如访问该站点)。在应用程序启动时,您可以运行任何虚拟查询或上面的Attach
或手动调用EF初始化:
using (var context = new MyContext())
{
context.Database.Initialize(false);
}
修改强>
我忘记了最后的解决方案。只需忽略6或7秒。如果您的站点出名并且流量合理,则不太可能发生冷查询,因为IIS工作进程很少会关闭AppDomain。偶然发生这种关闭的夜间用户偶然会发生这种情况,可能太累了甚至没有注意到延迟。