【发布时间】:2011-04-22 21:52:25
【问题描述】:
正如标题所示,我在使用 Entity Framework 对 SQL Server 数据库进行第一次查询时遇到问题。
我曾尝试在不同的网站上寻找答案,但似乎没有人能真正解决这个问题。
我正在从数据库中加载很多行,包括两个 0-many 关系。
测试是在 Visual Studio 2010 中使用 Entity Framework 4.0 模型和 POCO 生成器完成的(普通实体和 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。我为文字墙道歉:)
2010 年 19 月 10 日编辑:
我昨天做了一个测试,似乎支持按顺序返回行。这意味着当从数据库返回一行时,它会立即具体化(如果它在上下文中不存在),然后返回下一行,依此类推。
这就是查询在数据库服务器上花费大量时间的原因,因为实现时间包含在 SQL Server 分析器计时中。
我不认为这是 SQL Server 从硬盘读取的情况。 每次在 EF 中存在“第一个查询”时,都会发生慢查询。
例如
- 使用 EF 运行第一个查询,SQL 语句比任何辅助查询都慢
- 处置上下文/存储库
- 创建新上下文
- 运行与之前相同的查询(同样,第一个查询很慢,SQL 语句也很慢)
这几乎就像 EF 在第一个查询中发送一些选项一样使服务器变慢。
关于查询编译,我记得查询是在第一次使用时编译的,这意味着第一个查询需要更长的时间才能执行。
辅助查询会更快,但辅助查询的速度不是问题。
我还做了一个测试,我创建了一个静态的编译查询,以便为所有创建的上下文编译它。
然后我创建了一个上下文,运行了查询,销毁了上下文并创建了一个新的上下文并再次运行了相同的查询。
差异并没有那么大,只有几秒钟,而且我第一次运行查询时,只要不预编译它,它仍然需要很长时间。
至于视图生成,我们已经使用 T4 模板实现了这一点。
答案真的是 EF 只有在您只返回相对少量数据的最简单查询之外什么都不做的情况下才有效?
【问题讨论】:
-
我刚刚在一个旧项目中遇到了这个问题,即使这已经 9 年了,也没有真正带来解决方案的答案,是否有任何更新的 EF 版本解决了这个问题?
标签: .net performance entity-framework