EF加入5个大表 - Include()方法优化

时间:2017-05-28 13:32:49

标签: c# sql-server database performance entity-framework

我有以下数据库结构(EDMX模型):

public class Company 
{
    public Guid Id { get; set; }
    public virtual ICollection<Location> Locations { get; set; }
    // ... 15 more columns
}

public class Location 
{ 
    public Guid Id { get; set; }
    public virtual Company Company { get; set; }
    public Guid CompanyId { get; set; }

    public virtual ICollection<ReportA> ReportsA { get; set; }
    public virtual ICollection<ReportB> ReportsB { get; set; }
    public virtual ICollection<ReportC> ReportsC { get; set; }
    // ... 15 more columns with information - name, description etc.
}

public class ReportA
{
    public virtual Location Location { get; set; }
    public Guid LocationId { get; set; }
    // 30 more columns of type "int?"
}

public class ReportB
{
    public virtual Location Location { get; set; }
    public Guid LocationId { get; set; }
    // 30 more columns of type "int?"
}

public class ReportC
{
    public virtual Location Location { get; set; }
    public Guid LocationId { get; set; }
    // 30 more columns of type "int?"
}

一家公司可以拥有多个地点。每个地点都有许多来自A,B和C的报告 ReportAReportBReportC表格中的列不同 Report个表中的每一个都有大约40 000行 CompanyLocation表有~5000行

我需要获取所有数据并制作摘要报告 代码是:

 using (ComapnyEntities dataBaseContext = new ComapnyEntities())
 {
      IQueryable<Locations> query = dataBaseContext.Locations
            .AsNoTracking()
            .Where(location => companyIds.Contains(location.CompanyId))
            .Include(location => location.Company)
            .Include(location => location.ReportsA)
            .Include(location => location.ReportsB)
            .Include(location => location.ReportsC);
       // more filtation 
       return query.ToList();

       // assume that companyIds have all company Ids 
}

在大多数情况下,我可以使用Skip()Take()方法来提高执行速度(例如.Take(10)),但在一个特殊情况下,我需要提取所有位置以及公司信息, ReportsA,ReportsB,ReportsC。

基于Stackoverflow中的注释,Include()按行生成笛卡尔积。 https://stackoverflow.com/a/22625208/6142097

 // so if that is true:
 4 000 * 4 000 * 40 000 * 40 000 * 40 000 = ?? (1.024e+21)

“好的部分”是页面加载(本地)需要15秒,但在生产中不一样,需要更长的时间。

那么有没有办法提高查询的性能?

  • 我试过Entity-framework code is slow when using Include() many times - 它的速度慢了
  • 我添加了{C <1}},Location.CompanyIdReportA.LocationIdReportB.LocationIdReportC.LocationId的非Clustured索引 - 没有区别(我不确定索引是正确添加)
  • 无法构造连接所有表的本机SQL查询,这些表可以执行不到10秒。
  • 我试图将LocationId替换为.Inlude(),但没有真正的区别。

我的机器正在使用带有Windows 8.1的SQL Server 2014

你有什么建议?有没有办法改进我的代码?

1 个答案:

答案 0 :(得分:4)

  

我需要获取所有数据并制作摘要报告。

您不应该“获取所有数据”来“制作摘要报告”。而是编写返回摘要的查询,而不是每一行。