【问题标题】:C# - Entityframework and SQL Server linq nested loop join and hashjoin performanceC# - 实体框架和 SQL Server linq 嵌套循环连接和哈希连接性能
【发布时间】:2018-08-31 11:04:58
【问题描述】:

我想做一个左外连接来获取一些数据。但是,尽管在有用的列上创建了一些索引,但使用 Entity Framework 和 C# LINQ 连接时我的性能确实很差。我尝试了另一种方法,将多个连续的 FROM 与 WHERE 子句一起使用,并看到了性能的巨大提升。

我想知道为什么 SQL Server 不选择更快的连接类型?我是否对我的 LINQ 查询连接做错了什么导致性能如此糟糕?

这里是第一个耗时超过 3s 的版本:

from calendarEvent in calendarEvents
join participants in ctx.CalendarEventParticipants on calendarEvent.Id equals participants.CalendarEventId into calendarEventWithParticipants
from subCalendarEventWithParticipant in calendarEventWithParticipants.DefaultIfEmpty()
select new { calendarEvent , subCalendarEventWithParticipant };

以及耗时 200ms 的版本:

from calendarEvent in calendarEvents
from participants in ctx.CalendarEventParticipants.Where(cep => cep.CalendarEventId == calendarEvent.Id).DefaultIfEmpty()
select new { calendarEvent , participants };

我在CalendarEventParticipants.calendarEventId 上有一个有用的索引。

我主要担心的是,理论上,带有连接的查询应该比带有 where 的第二个查询快得多。使用 SSMS,我可以看到查询在执行 NESTED LOOPS(左外连接)之前没有 JOIN,这在此查询上花费了我很多。

谢谢

【问题讨论】:

  • 请试着想象读者回答问题需要什么。您不知道生成了哪个 SQL,因此我们不知道您所说的“更快的连接类型”是什么意思。此外,了解您使用的 ORM(+ 版本!)也很重要。而且通常类定义和映射也是相关的,因为必需和非必需的关联在连接中表现不同。
  • 什么是hashjoin
  • @GertArnold:你好!这是 C# 代码,所以这里没有显示 SQL。我确实可以转储发送到 SQL SERVER 的查询,但这真的很难理解。我们使用实体框架。
  • @NetMage:你好!请参考stackoverflow.com/a/3038742/10299666
  • 您似乎没有意识到 C# 代码只不过是生成 SQL 的工具。无论用 C# 写什么关于 LINQ 的内容,即 LINQ-to-objects,这里都不适用。如果要优化什么,那就是 SQL 代码。这就是 SQL 和映射至少与 LINQ 查询一样相关的原因。

标签: sql-server performance linq


【解决方案1】:

首先您的查询不清楚。您将 CalendarEventId 与 calendarEvent.Id 进行比较的方式

from calendarEvent in calendarEvents

from participants in ctx.CalendarEventParticipants.Where(cep => cep.CalendarEventId == calendarEvent.Id).DefaultIfEmpty()
select new { calendarEvents, participants };

其次,上面的查询看起来像一个嵌套查询,它总是一个性能消耗者。另一个花费较少时间的查询是使用连接,它为您提供联合目标集以进行处理。性能取决于索引、大小和其他因素。但是如果表很大,那么嵌套查询就不是正确的选择。而是使用连接。

from calendarEvent in calendarEvents
join participants in ctx.CalendarEventParticipants on calendarEvent.Id equals participants.CalendarEventId into calendarEventWithParticipants

from subCalendarEventWithParticipant in calendarEventWithParticipants.DefaultIfEmpty()
select new { calendarEvents, subCalendarEventWithParticipant };

【讨论】:

  • 我的主要问题是,与使用 where 子句的查询相比,使用 join 的查询需要 3 秒才能运行。我更新了我的帖子以添加更多详细信息。
猜你喜欢
  • 1970-01-01
  • 2014-06-26
  • 2011-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-08
  • 2019-06-24
相关资源
最近更新 更多