6

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

我看过一篇关于使用应用程序自动启动的文章,我的问题是:有没有办法触发这个查询来导致任何缓存需要发生而不实际调用查询,或者我有必要只用一组虚拟参数调用查询?

编辑:当我说六秒时,我指的是获取查询所需的时间。代码看起来像这样(注意在这种情况下,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 之前。我现在正在尝试设置一瞥,看看它是否可以为我提供有关可能同时发生的其他事情的更多详细信息。

4

1 回答 1

3

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

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

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

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

另一种方法是触发加载您的 Web 应用程序定期启动(例如,通过一些访问站点的过程)。在应用程序启动中,您将运行任何虚拟查询或Attach上述内容或手动调用 EF 初始化:

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

编辑

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

于 2013-05-06T20:50:02.493 回答