实体框架 - 第一次查询缓慢

Ken*_*sen 24 .net performance entity-framework

正如标题所示,我在使用Entity Framework对SQL Server数据库进行第一次查询时遇到问题.

我试过在不同的网站上寻找答案,但似乎没有人真正找到解决方案.

我从数据库中加载了很多行,包括两个0-many关系.

使用Entity Framework 4.0 Model和POCO生成器在Visual Studio 2010中完成测试(普通实体和POCO对象之间的时序差别不大).我还使用T4视图模板预编译视图.

该数据库位于SQL Server 2008上.

我真正想知道的是为什么第一个查询比任何二级查询都慢得多.

我还想知道是否可以采取措施将第一个查询的速度提高到可接受的范围内.

这是一个很大的查询,我们可能会得到更大的其他查询,并且可以理解它们可能有点慢但是30秒对于用户来说太慢了等待,特别是当数据集可以更快地获得相同的数据时.

我已经做了一些时间测试,试图找出问题所在,我有点惊讶地发现它看起来像第一次查询的SQL Server速度慢.

时间安排如下:

.NET测试应用程序:

  • 第一次查询:29,6秒
  • 第二次查询:3,2秒

SQL事件探查器:

  • 第一次查询:27秒
  • 第二次查询:3,2秒

SQL Server查询窗口

  • 第一次查询:8秒
  • 第二次查询:4秒

申请中的时间是用Stopwatch班级测量的.仅测量了查询并.ToList()用于执行查询.

SQL Server Profiler中的计时用于在应用程序中执行的相同查询,该查询显示应用程序仅使用大约2,6秒将数据填充到对象中.

最后27秒用于在SQL Server上执行查询.

查看辅助查询,应用程序和SQL服务器的计时相同,但这次执行查询的速度要快得多.

我可以理解为什么应用程序不会随时使用,因为没有新行需要转换为对象,但为什么查询速度要快得多,因为执行计划而不是24秒,我预计会有几秒钟.

出于测试目的,我复制了实体框架生成的SQL,并打开了一个带有单独连接的新查询窗口,并在其中执行了查询.

如您所见,第一个查询需要8秒,第二个查询需要4秒.

我希望有人有一些建议.

PS.我为文字墙道歉:)

编辑19-10-2010:
昨天我做了一个测试似乎支持以顺序方式返回行.这意味着当从数据库返回一行时,它会立即实现(如果它在上下文中尚不存在),则返回下一行,依此类推.

这就是为什么查询在数据库服务器上占用大量时间的原因,因为实现时间包含在SQL Server探查器计时中.

我不相信这是从硬盘读取SQL Server的情况.每次在EF中存在"第一个查询"时,都会发生慢速查询.

恩.

  1. 使用EF运行第一个查询,SQL语句比任何辅助查询慢
  2. 处理上下文/存储库
  3. 创建一个新的上下文
  4. 运行与以前相同的查询(同样第一个查询很慢,SQL语句也是如此)

这几乎就像EF发送一些选项以及使服务器变慢的第一个查询.

至于查询编译,我记得第一次使用它时编译了查询,这意味着第一个查询执行的时间会更长.

辅助查询会更快,但辅助查询的速度不是问题.

我还做了一个测试,我在其中创建了一个编译的查询作为静态,以便为所有创建的上下文编译它.

然后我创建了一个上下文,运行查询,销毁了上下文并创建了一个新的并再次运行相同的查询.

差异不是那么大,只有几秒钟,而且我第一次运行查询时,它仍然只需要预先编译就可以了.

至于视图生成,我们已经使用T4模板实现了这一点.

答案真的是EF只有在除了只返回相对少量数据的最简单查询之外什么都不做的情况下才有效吗?

小智 13

我们在EF 5.0中遇到了同样的问题,到目前为止,一个肤浅的谷歌搜索并没有显示出足够的加速.

根据此链接http://msdn.microsoft.com/en-us/library/cc853327(v=vs.100).aspx "加载元数据"具有适中的时间成本,但每个AppDomain只需要发生一次.我没有发现预编译像加载元数据的技巧.

我们实现的解决方法是在应用程序启动时在单独的线程中对Context进行次要查询.这会加载元数据,它仍然需要很长时间(在我们的情况下为18-19秒),但应用程序在加载过程中会响应.第一次实际负载也不会花费太长时间.

请注意,在我们的上下文中,用户可能需要在应用程序中花费18-19秒才能进行EF调用以响应其操作.显然,如果在您的应用程序中无法做到这一点,那么这项工作可能无法提高速度.


Son*_*onu 7

我有同样的问题.我用一个技巧来解决这个问题.由于Entity框架在第一次访问时需要花费更多时间,然后在第一次缓存部分结果(sql server也会单独缓存结果).所以我在我的应用程序上异步启动了Entity框架.它对我有用.我的申请变得更顺畅了.

在Global.asax页面中

 protected void Application_Start()
    {

        Start(() =>
        {
            using (EF.DMEntities context = new EF.DMEntities())
            {
                context.DMUsers.FirstOrDefault();
            }
        });
    }
    private void Start(Action a)
    {
        a.BeginInvoke(null, null);
    } 
Run Code Online (Sandbox Code Playgroud)


Cra*_*ntz 4

嗯,很多事情都会导致 SQL Server 查询第一次运行时变慢。然而,大多数都不需要几秒钟。

\n\n

\xe2\x80\xa6 硬盘随机访问除外。第一次运行查询时,SQL Server 可能必须从硬盘存储读取数据库页。下次运行查询时,这些页面可能会在内存中。

\n\n

对于实体框架,第一次运行查询时必须将其编译为 SQL。您可以使用该CompiledQuery类型预编译实体框架查询,以便在最终用户必须等待之前提前完成此工作。

\n\n

在非常大的模型上,视图生成也需要一些时间。您可以将其移至编译时间。有关更多此类提示,请参阅本文。

\n