为什么这个EF查询需要这么长时间?

时间:2016-11-10 17:06:34

标签: sql-server entity-framework

我们有一个EF4查询,大约需要10秒钟才能完成。查询并不复杂,但由于包含了大量相关表格,因此需要花费很长时间。我试图加快速度。

原始查询看起来像这样(为了清晰起见缩短了......)

var supportTickets = ctx.SupportTickets
  .Include(s => s.System.Customer.Country)
  .Include(s => s.System.Site.Address.Country)
  // other includes omitted
  .OrderByDescending(s => s.ID)
  .ToList();
var ticketsList = supportTickets
  .Select(CreateSupportTicketListOverview)
  .ToList();

CreateSupportTicketListOverview()是一种获取实体并根据它返回DTO的方法。它的缩短版本看起来像这样......

private static SupportTicketListOverview CreateSupportTicketListOverview(SupportTicket x)
  {
    return new SupportTicketListOverview {
      ID = x.ID,
      SystemNumber = x.System != null ? x.System.SystemNumber : "",
      CustomerName = x.System != null && x.System.Customer != null ? x.System.Customer.Name : "",
      ShortSummary = x.ShortSummary,
      SiteName = x.Site != null ? x.Site.SiteName : "",
      Status = x.Status != null ? x.Status.Description : "",
      // other properties omitted for clarity
    };
  }

正如我所说,这需要大约10秒钟,并返回不到4000的结果。 SQL Server Profiler显示查询大约需要6.6秒。如果我们复制生成的SQL并单独运行它,它只需要大约2秒钟,这让我感到困惑。为什么单独运行它会更快?创建实体所需的时间不会包含在数据库查询中吗?如果是的话,剩下的时间是做什么的呢?

我试图通过关闭跟踪并从数据库中提取所需数据而不是完整实体来改进这一点。修改后的代码看起来像这样(为了清晰起见再次缩短)......

  var tickets = ((SalesTrackerCRMEntities) getContext()).SupportTickets
      .AsNoTracking()
      .Include(s => s.System.Customer.Country)
      .Include(s => s.System.Site.Address.Country)
      .OrderByDescending(s => s.ID)
      .Select(t => new {
        SystemNumber = t.System != null ? t.System.DHRNumber : "", t.ID,
        CustomerName = t.System != null && t.System.Customer != null ? t.System.Customer.Name : "",
        SiteName = t.Site != null ? t.Site.SiteName : "",
        Status = t.Status != null ? t.Status.Description : "",
        // other stuff omitted
      })
      .AsEnumerable();
  var tickets1 =tickets
      .Select(t => new SupportTicketListOverview {
        ID = t.ID,
        SystemNumber = t.SystemNumber,
        CustomerName = t.CustomerName,
        ShortSummary = t.ShortSummary,
        SiteName = t.SiteName,
        Status = t.Status,
        // other stuff omitted
      })
      .ToList();

令我惊讶的是,这需要大约15秒才能完成。查看分析器,数据库查询本身需要大约0.7秒,即比原始查询快10倍 ,但EF查询总体上需要50%更长

所以我完全糊涂了。我做了一些搜索,但我找到的所有建议都是针对我已经做过的事情。例如,this blog post提供了七种提高EF性能的方法。这些包括不使用存储库模式(因为他没有展示如何做或不做的任何示例,因为他没有真正确定他在这里的意思),而不是使用分页(我们不会这样做)。 t),使用投影(我们至少在新查询中),关闭延迟加载(它已经关闭),关闭跟踪(已经完成)并使用表上的索引(我们已经是)。最后一个提示是减少查询次数。我们无法在这里看到我们如何做到这一点,因为我们需要所有相关数据。

总之,原始数据库查询需要6.6秒,整个EF查询需要10秒。修订后的查询对于数据库部分需要.7s,而对于整个EF查询需要15s。所有这些都太长了。

是否有人能够建议我如何加快查询速度?感谢

1 个答案:

答案 0 :(得分:0)

您使用的是哪个版本的SQL Server?如果是2016年,您可以启用查询存储(https://msdn.microsoft.com/en-us/library/dn817826.aspx)并查找EF4查询正在执行的t-sql查询。如果它是旧版本,您可以在运行EF4查询时使用此(http://blog.sqlauthority.com/2009/01/07/sql-server-find-currently-running-query-t-sql/)查找查询文本,并通过对服务器运行查询并分析计划/缺失索引/等来查看查询速度慢的原因。 / p>