LINQ to实体查询速度慢

时间:2014-12-13 12:18:45

标签: c# linq entity-framework azure-sql-database database-performance

我的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中生成的查询时,我在每次运行时都会获得良好的查询执行时间,因此数据库设计不应成为问题,尽管它可能不是最有效的解决方案反正。

1 个答案:

答案 0 :(得分:0)

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

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

查看此帖子中的some tips on consuming views in EF