简体   繁体   English

LINQ到实体的查询变慢

[英]LINQ to entities slow query

I have a huge problem with Sql Server query execution time which I've debugged for a long time with no success. 我对Sql Server查询执行时间遇到了巨大的问题,该问题已经调试了很长时间,但没有成功。

Basically I'm generating a report where 'Order' statistics are grouped by order and shown to the user. 基本上,我正在生成一个报告,其中“订单”统计信息按订单分组并显示给用户。 The problem is, that most of the time the query execution is reasonably fast, but occasionally it plummets and causes timeouts on the server. 问题是,大多数情况下查询执行速度相当快,但偶尔会直线下降并导致服务器超时。

What I've gotten myself from it is that the occasional poor query performance seems to be caused by parameter sniffing in the SQL Server. 我从中得到的是,偶尔的查询性能差似乎是由SQL Server中的参数嗅探引起的。 My relations have very mixed amount of related rows; 我的关系中有很多相关行。 some relation might have 10 000 rows for one parent row but the next row could have only 1 related row. 某个关系可能有1万行用于一个父行,但下一行可能只有1个相关行。 I think this causes the Query optimizer in some cases to ignore indexes completely and cause really poor performance. 我认为这会使查询优化器在某些情况下完全忽略索引,从而导致性能下降。

Basically I have no idea how to approach with a fix to this problem. 基本上我不知道如何解决此问题。 I either have to optimize my query below somehow OR come up with some way to force the query optimizer to use indexes every time. 我要么必须以某种方式优化我的查询,要么想出某种方式来强制查询优化器每次都使用索引。 Stored procedures are not an option in this project, unfortunately. 不幸的是,存储过程不是该项目的选项。

What I've tried is to create independent requests for every 'Order', but as theres over 1000 orders in the system, that causes massive slowness and really isn't an option. 我尝试过的是为每个“订单”创建独立的请求,但是由于系统中有超过1000个订单,这会导致大量的运行缓慢,实际上是不可行的。 The closest I've gotten to get it to run within a reasonable execution time is the query below which in turn seems to suffer from the parameter sniffing problem. 我最想让它在合理的执行时间内运行的查询是下面的查询,而该查询似乎又遭受参数嗅探问题的困扰。

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;

Any help and ideas about how to make my reporting run reasonably fast every time would be greatly appreciated - no matter if it's query optimizing itself or some awesome ideas for reporting in SQL in general. 我们将不胜感激有关如何使我的报告每次都能以合理的速度快速运行的任何帮助和想法-无论是查询自身优化还是一般而言,SQL中一些很棒的想法。

I'm using Azure SQL if that makes any difference. 如果这有任何区别,我正在使用Azure SQL。

Also note that when I'm running the generated query from the LINQ above in SSMS I get good query execution time on every single run so the DB design shouldn't be a problem here albeit it might not be the most efficient solution anyway. 还要注意,当我在SSMS中从上面的LINQ运行生成的查询时,每次运行都会获得良好的查询执行时间,因此DB设计在这里应该不是问题,尽管它可能仍然不是最有效的解决方案。

Maybe not an answer for your, just a thought. 也许不是您的答案,只是一个想法。 You could create a view for your report, and then query the view to get your results. 您可以为报表创建一个视图,然后查询该视图以获取结果。 This would ensure that the query runs fine in SQL every time, from what you are saying. 这将确保您每次所说的查询都能在SQL中正常运行。

You use them similar to tables, and can make any queries on them. 您可以像使用表一样使用它们,并且可以对它们进行任何查询。

Check this post for some tips on consuming views in EF . 查看此帖子以获取有关在EF中使用视图的一些提示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM