【问题标题】:Why does this query take so long in Entity Framework, when it's so fast in SQL?为什么这个查询在 Entity Framework 中需要这么长时间,而在 SQL 中却如此之快?
【发布时间】:2015-04-29 15:28:51
【问题描述】:

我有一个名为 GeographicalLocations 的表,其中包含大约 57K 行。如果我在 SQL Server Management Studio 中运行以下查询,大约需要 1-2 秒才能完成...

select * from GeographicalLocations where Active=1

如果我在 LinqPad 中做同样的事情,大约需要 2-3 秒...

GeographicalLocations.Where (gl => gl.Active)

但是,使用 EF4 的存储库中的相同代码大约需要 10-11 秒...

List<GeographicalLocation> geographicalLocations = new SalesTrackerCRMEntities()
  .CreateObjectSet<GeographicalLocation>()
  .Where(g => g.Active)
  .ToList();

顺便说一下,我们目前卡在 EF4 上,所以请不要建议升级。我很乐意,但目前还有其他因素阻碍了我们。

知道如何加快速度吗?用户抱怨响应缓慢。显然不是数据库,因为 SQL 查询本身非常快。好像跟EF有点关系,不过不知道是什么。

我在上面运行了 SQL Profiler,并且可以看到发送的 SQL。在 SSMS 中运行不到一秒,但分析器显示批次开始和结束之间有 10 秒的间隔。不确定这里发生了什么,因为我原以为 EF 会提取所有数据,然后将其具体化为实体,但看起来它可能正在这样做。

无论如何,如果我有任何关于如何提高性能的想法,我将不胜感激。

【问题讨论】:

  • 单独创建上下文并重试。创建上下文需要时间
  • 试过了,没有任何区别。即使使用现有上下文,查询也需要很长时间。还有其他想法吗?谢谢
  • 运行分析器(例如 DotTrace,30 天免费),看看瓶颈在哪里。
  • 当您声明“如果我在 SQL Server Management Studio 中运行以下查询,大约需要 1-2 秒才能完成...” - 是结果开始进入您的结果窗格- 或 - 完成查询(接收所有记录,提供记录计数,并停止查询计时器)?
  • @Mike,返回所有结果,提供记录计数并停止查询计时器。

标签: sql-server performance entity-framework


【解决方案1】:

在对 DbSet 使用 LINQ 表达式时,您正在利用 IQueryable 接口。 IQueryables 被评估为 SQL 语句,然后针对您的数据库执行。如果您想提高性能,可以使用如下的原始 SQL 语句查询 DbSet 属性:

var locations = db.GeographicalLocations.SqlQuery("SELECT * FROM GeographicalLocations WHERE Active = 1").ToList();

【讨论】:

  • 下降到 SQL 是核心选项。我会先用尽其他选项。
  • 就像usr说的,插入SQL确实不是个好主意。但是,我发现关闭跟踪会带来完全相同的性能提升,请参阅我的答案。感谢您的建议。
【解决方案2】:

在胡闹之后,我发现下面的时间不到 200 毫秒(与之前的大约 11 秒相比)......

var geographicalLocations = getContext().CreateObjectSet<GeographicalLocation>()
    .AsNoTracking()
    .Where(g => g.Active).ToList()

这样做的缺点是它不会加载相关实体,因此您必须在之后手动加载它们,但它提供了如此巨大的性能提升,因此非常值得(至少在这种情况下)。

您必须单独评估每个案例,看看额外的速度是否值得额外的代码。

希望这会有所帮助。感谢大家的回复。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-27
    • 2015-08-11
    • 2021-11-27
    • 1970-01-01
    • 1970-01-01
    • 2011-12-07
    • 1970-01-01
    相关资源
    最近更新 更多