LINQ 到实体的查询速度很慢

本文关键字:速度 查询 实体 LINQ | 更新日期: 2023-09-27 18:34:15

我在 Sql Server 查询执行时间方面遇到了一个巨大的问题,我已经调试了很长时间但没有成功。

基本上,我正在生成一份报告,其中"订单"统计信息按订单分组并显示给用户。问题是,大多数情况下,查询执行速度相当快,但偶尔会骤降并导致服务器上超时。

我从中得到的是,偶尔的查询性能不佳似乎是由SQL Server中的参数嗅探引起的。我的关系有非常多的相关行;某个关系可能有一个父行有 10 000 行,但下一行可能只有 1 个相关行。我认为这会导致查询优化器在某些情况下完全忽略索引并导致性能非常差。

基本上我不知道如何解决这个问题。我要么必须以某种方式优化下面的查询,要么想出一些方法来强制查询优化器每次都使用索引。遗憾的是,存储过程不是此项目中的选项。

我尝试的是为每个"订单"创建独立的请求,但由于系统中有超过 1000 个订单,这会导致巨大的缓慢,实际上不是一种选择。我最接近让它在合理的执行时间内运行的是下面的查询,它反过来似乎又遇到了参数嗅探问题。

result = (from ord in db.Orders
  join comm in db.Comments.Where(i => 
    i.UserId == userId &&
    i.Created >= startDate && 
    i.Created < endDate && 
    i.UserGroupId == channelId && 
    i.Campaign.CampaignCountryId == countryId && 
    (i.CommentStatus.Name == CommentStatus.Approved || i.CommentStatus.Name == CommentStatus.Pending)) 
  on ord.OrderId equals comm.OrderId into Comments
  join motif in db.Motifs.Where(i => 
    i.UserId == userId && 
    i.Created > startDate && 
    i.Created < endDate && 
    i.UserGroupId == channelId && i.Campaign.CampaignCountryId == countryId) 
  on ord.OrderId equals motif.OrderId into Motifs
  where ord.EndDate > startDate
  select new ReportRow()
  {
      OrderName = ord.Name,
      OrderId = ord.OrderId,
      ChannelId = channelId,
      Comments = Comments.Count(c => c.CommentStatus.Name == CommentStatus.Approved),
      PendingComments = Comments.Count(c => c.CommentStatu.Name == CommentStatus.Pending),
      Motifs = Motifs.Count(),
      UniqueMotifs = Motifs.GroupBy(c => c.Uin).Count(),
      ApprovedValue = ((decimal?)Motifs.GroupBy(c => c.Uin).Select(c => c.FirstOrDefault()).Sum(c => c.Value) ?? 0) + ((decimal?)Comments.Where(c => c.Commentstatu.Name == Commentstatus.Approved).Sum(c => c.Value) ?? 0),
      PendingValue = ((decimal?)Comments.Where(c => c.Commentstatu.Name == Commentstatus.Pending).Sum(c => c.Value) ?? 0)
  }).ToList();
return result;

任何关于如何使我的报告每次都运行得相当快的帮助和想法将不胜感激 - 无论是查询优化本身还是一些关于SQL报告的很棒的想法。

我正在使用Azure SQL,如果这有什么不同的话。

另请注意,当我在 SSMS 中运行从上面的 LINQ 生成的查询时,每次运行都会获得良好的查询执行时间,因此数据库设计在这里应该不是问题,尽管它可能不是最有效的解决方案。

LINQ 到实体的查询速度很慢

也许不是你的答案,只是一个想法。您可以为报表创建一个视图,然后查询该视图以获取结果。这将确保查询每次在SQL中都能正常运行,从您所说的内容来看。

您可以使用它们类似于表,并且可以对它们进行任何查询。

查看这篇文章,了解有关在 EF 中使用视图的一些提示。