【问题标题】:EntityFramework taking excessive time to return records for a simple SQL queryEntityFramework 花费过多时间来返回简单 SQL 查询的记录
【发布时间】:2015-09-14 18:51:33
【问题描述】:

这篇老文章我已经梳理过了: Why is Entity Framework taking 30 seconds to load records when the generated query only takes 1/2 of a second? 但没有成功。

我已经测试了查询:

  • 没有延迟加载(不使用 .Include 相关实体)和
  • 没有合并跟踪(使用 AsNoTracking)

由于查询的复杂性和使用 Code First 模型,我认为我一般不能轻易切换到已编译的查询,但如果您遇到其他情况,请告诉我...

设置

  • 实体框架“4.4”(安装 EF 5 的 .Net 4.0)
  • Code First 模型和 DbContext
  • 直接在托管数据库的 SQL Server 2008 机器上进行测试

查询 - 它只是从一个表中返回简单的字段:

SELECT 
[Extent1].[Id] AS [Id], 
[Extent1].[Active] AS [Active], 
[Extent1].[ChangeUrl] AS [ChangeUrl], 
[Extent1].[MatchValueSetId] AS [MatchValueSetId], 
[Extent1].[ConfigValueSetId] AS [ConfigValueSetId], 
[Extent1].[HashValue] AS [HashValue], 
[Extent1].[Creator] AS [Creator], 
[Extent1].[CreationDate] AS [CreationDate]
FROM [dbo].[MatchActivations] AS [Extent1]
  • MatchActivations 表与其他表有关系,但出于此目的,需要根据需要显式加载相关实体。

结果(来自 SQL Server Profiler)

  • 对于 Microsoft SQL Server Management Studio 查询:CPU = 78 毫秒,持续时间 = 587 毫秒。
  • 对于 EntityFrameworkMUE:CPU = 31 毫秒,持续时间 = 8216 毫秒!

有谁知道,除了建议使用编译查询之外,在使用实体框架进行这样一个简单的查询时还有什么需要注意的吗?

【问题讨论】:

标签: entity-framework sql-server-2008 entity-framework-4 ef-code-first database-performance


【解决方案1】:

许多人遇到了这样的问题:由于参数嗅探导致 SQL Server 在通过 ADO.NET 运行查询时生成非常低效的执行计划,而直接从 SQL Server 管理中运行完全相同的查询Studio 使用不同的执行计划,因为默认情况下查询上的某些标志设置不同。

有些人报告说,通过运行以下一个或两个命令来强制刷新查询执行计划是成功的:

 DBCC DROPCLEANBUFFERS
 DBCC FREEPROCCACHE

但是,针对此问题的更长期、更有针对性的解决方案是使用 OPTIMIZE FOROPTION(Recompile) 之类的查询提示,如 this article 中所述,以帮助确保在第一名。

【讨论】:

    【解决方案2】:

    如果你说的是真的,我认为框架正在做一些时髦的事情,即在管理工作室中运行查询需要半秒,而实体框架需要 8.2 秒。我的预感是它正在尝试对那些 25K+ 记录集做一些事情(可能绑定到其他东西)。

    您可以下载一次 NP NET 分析器并分析您的应用程序吗? http://www.microsoft.com/en-in/download/details.aspx?id=35370

    这个漂亮的小程序将记录每个方法调用及其执行时间,并且基本上可以从引擎盖下为您提供关于它花费这 7 秒以上的时间的信息。如果这没有帮助,我还建议尝试 JetBrains .NET 分析器。 https://www.jetbrains.com/profiler/

    先前的回答表明执行计划可能会关闭,这在许多情况下都是正确的,但有时也值得深入了解一下以确定原因。

    【讨论】:

      【解决方案3】:

      感谢 Kalagen 和其他对此做出回应的人 - 我确实对此得出了结论,但忘记了这篇文章。

      它是返回的记录数 X 处理时间(我假设为 LINQ/EF),以将原始 SQL 数据重新用于客户端上的对象。我在 SQL 服务器上设置了 wireshark 来监控它和客户端机器之间的网络流量,并在查询后发现:

      • 在 SQL Server 和 SQL Server 之间存在恒定的网络流量流 不同机器之间的数据包处理速率差异很大 (8x)
      • 发生这种情况时,SQL Server CPU 利用率小于 25%,并且似乎没有发生资源匮乏(工作集、虚拟内存、线程、句柄计数等)

      所以它基本上是将结果不断转换回 EF 对象。

      顺便说一句,有问题的查询是“性能”单元测试的一部分,因此我们最终将其剔除为在 1 秒内加载 100 条记录的更合理的典型网页加载。很容易通过。

      如果有人想详细了解 Entity Framework 如何处理查询后记录,我相信这会很有用。

      这是一个有趣的发现,处理时间更多地取决于客户端计算机而不是 SQL 服务器计算机(这是一个 Intranet 应用程序)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-10
        • 2017-08-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多