c# - LINQ to 实体慢查询

标签 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 生成的查询时,我在每次运行时都获得了良好的查询执行时间,因此数据库设计在这里应该不是问题,尽管它可能不是最有效的解决方案无论如何。

最佳答案

也许不是你的答案,只是一个想法。您可以为您的报告创建一个 View ,然后查询该 View 以获得您的结果。根据您所说的,这将确保查询每次都能在 SQL 中正常运行。

您可以像使用表格一样使用它们,并且可以对它们进行任何查询。

查看此帖子是否有 some tips on consuming views in EF .

关于c# - LINQ to 实体慢查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27458679/

相关文章:

c# - 敏捷 html 解析器从缓冲区/流中读取

asp.net-mvc - 使用 ToExpando 方法的问题

c# - 查询返回匿名类型列表,需要值列表

html - CsQuery - 获取两个选择器之间的兄弟值?

wcf - EF4 POCO WCF 序列化问题(无延迟加载、代理/无代理、循环引用等)

c# - AutoMapper IQueryable Extension 抛出 "Cannot compare elements of type <Complex Type>"

c# - 按 Entity Framework 中子列表的第一项对集合进行排序

c# - 为什么我得到 CS1012 : "Too many characters in character literal" and CS0019?

c# - 是否可以在 .NET 4.0 框架上使用 TLS1.2 发送 HttpWebRequest

c# - 如何在 ajax 请求后更改 URL?