如何解决C#-使用GroupBy的LINQ Lambda表达式-为什么嵌套验证是如此低效? 性能不佳查询:新查询
我度过了糟糕的一天,尝试使用Entity Framework提高C#中下一个查询的性能(信息存储在SQL Server中,并且结构使用“代码优先”方法-但这此时不重要):
性能不佳查询:
var projectDetail = await _context
.ProjectDetails
.Where(pd => projectHeaderIds.Contains(pd.IdProjectHeader))
.Include(pd => pd.Stage)
.Include(pd => pd.ProjectTaskStatus)
.GroupBy(g => new { g.IdProjectHeader,g.IdStage,g.Stage.StageName })
.Select(pd => new
{
pd.Key.IdProjectHeader,pd.Key.IdStage,pd.Key.StageName,TotalTasks = pd.Count(),MissingCriticalActivity = pd.Count(t => t.CheckTask.CriticalActivity && t.ProjectTaskStatus.Score != 100) > 0,Score = Math.Round(pd.Average(a => a.ProjectTaskStatus.Score),2),LastTaskCompleted = pd.Max(p => p.CompletionDate)
}).ToListAsync();
几个小时后,我发现了问题,并且能够解决性能问题(现在花费了4分钟以上的时间,新查询只需要1-2秒):
新查询
var groupTotalTasks = await _context
.ProjectDetails
.Where(pd => projectHeaderIds.Contains(pd.IdProjectHeader))
.Select(r => new
{
r.IdProjectHeader,r.CompletionDate,r.IdStage,r.ProjectTaskStatus.Score,r.CheckTask.CriticalActivity,r.Stage.StageName
})
.GroupBy(g => new { g.IdProjectHeader,g.StageName })
.Select(pd => new
{
pd.Key.IdProjectHeader,MissingCriticalActivity = pd.Count(r => r.CriticalActivity && r.Score != 100) > 0,Score = Math.Round(pd.Average(a => a.Score),LastTaskCompleted = pd.Max(p => p.CompletionDate)
}).ToListAsync();
改善查询的步骤如下:
- 避免使用
nested validations
(例如Score
,它使用MainQuery.ProjectTaskStatus.Score
来计算average
) - 在查询中避免使用
Include
- 我使用
Select
仅获得GroupBy
中将使用的信息。
这些更改解决了我的问题,但是,为什么?
...而且仍然存在另一种改进此查询的方法?
使用嵌套验证使查询变得极其缓慢的原因有哪些? 其他更改对我来说更有意义。
解决方法
我最近读到,每当EF Core 2遇到无法为其生成SQL查询的任何内容时,它将切换到内存中评估。因此,第一个查询基本上是从数据库中拉出所有ProjectDetails,然后在应用程序的内存中进行所有分组等。这可能是您遇到的最大问题。
在这种情况下,使用.Include
会产生很大的影响,因为在拔出所有这些ProjectDetails时,您还包含了许多其他数据。现在您避免在内存中完成所有工作,这可能几乎没有影响。
他们意识到自己的错误,并且changed the behavior to throw an exception in cases like that starting with EF Core 3。
为避免将来出现此类问题,您可以升级到EF Core 3,或者只是非常小心以确保Entity Framework可以将查询中的所有内容转换为SQL。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。