C#-Entityframework和SQL Server linq嵌套循环联接和哈希联接性能

时间:2018-08-31 11:04:59

标签: sql-server performance linq

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

我想知道为什么SQL Server不选择更快的联接类型?我的LINQ查询联接是否做错了,以获得如此糟糕的性能?

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

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(左外连接)之前没有加入,因此在此查询上花费了我太多的钱。

谢谢

1 个答案:

答案 0 :(得分:0)

首先您的查询不清楚。比较CalendarEventId和calendarEvent.Id的方式

from calendarEvent in calendarEvents

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

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

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 };