【问题标题】:Slow Performance on searching through List in LINQ在 LINQ 中搜索列表时性能缓慢
【发布时间】:2018-07-09 10:16:39
【问题描述】:

我有一个表,其中包含任何特定月份的超过 200,000 条记录。

从表中获取记录不是问题,它按预期工作,但搜索记录显示性能非常慢

var listEmpShiftDetails =ctx.tblTO_ShiftSchedule
                            .Where(m => m.CompanyId == companyId &&
                                        m.ShiftDate >= fromdate &&
                                        m.ShiftDate <= todate)
                            .Select(m => m).ToList();

从数据库中获取的记录大约:200 000

var data = (from a in ctx.tblEmployee
             join b in ctx.tblTO_Entry  on a.Id equals b.EmployeeId
             where a.CompanyId == companyId && b.CompanyId == companyId &&
             (b.Entry_Date >= fromDate && b.Entry_Date <= toDate)                 
             select new { a, b }).ToList();

*ote: 下面的代码中没有调用数据库。所有数据都在上面获取

Linq Query 逐条获取记录

 foreach (var item in data) // Data consist of employee details 3k Records
   {          
       if (listEmpShiftDetails
           .Any(m => m.EmployeeId == item.a.Id && 
                     m.ShiftDate == item.b.Entry_Date))
       {
            var shiftDetails = listEmpShiftDetails
                               .Where(m => m.EmployeeId == item.a.Id && 
                                           m.ShiftDate ==item.b.Entry_Date)
                               .Select(m => m)
                               .FirstOrDefault();
                  //Other Calculations    
          }
    }

Above 2 Lines 执行时间过长,下面是 Visual Studio 的输出。如何提高性能?

分析器输出

【问题讨论】:

  • 您正在执行相同的查询两次。只做一次。
  • “20 万唱片”???
  • 200,000 条记录
  • 您是否需要第一行 - 只需检查第二行返回任何内容的结果。
  • @Nilesh - 您应该向我们展示您的完整代码。我们应该了解如何从数据库中检索所有数据以及如何准备这些数据。那么我们可以给你一个正确的答案。

标签: c# .net asp.net-mvc performance linq


【解决方案1】:

var listEmpShiftDetails = 从数据库中获取的记录大约:- 20 万条记录;

foreach (var item in data) // Data consist of employee details 3k Records
{
     var selectedItem = listEmpShiftDetails.FirstOrDefault(m => m.EmployeeId == item.Id && 
     m.ShiftDate == item.Entry_Date);
  if (selectedItem != null)
  {
     // Other Calculations    
  }
}

无需多次迭代相同的查询。你只需要第一个项目,如果它匹配否则为空。希望上面的查询能给你更好的性能。

【讨论】:

  • 更新上述代码后也需要 4-5 分钟
【解决方案2】:

查看您的查询后我的想法是什么:

  1. 额外的查询负载,无需检查 If(){}。
  2. 如果您的“listEmpShiftDetails”是IQueryable,那么listEmpShiftDetails.Any() 就可以了。但如果它是 List,那么它会妨碍性能。 Worth spending 5 mins Count Vs Any performance。
  3. 让您的查询保持简单。

    var shiftDetails = listEmpShiftDetails.FirstOrDefault(m => m.EmployeeId == item.Id && m.ShiftDate == item.Entry_Date);
    

【讨论】:

    【解决方案3】:

    首先,这样做可以避免执行两次查询:

    foreach (var item in data) // Data consist of employee details 3k Records
    {
        var shiftDetails = listEmpShiftDetails.Where(m => m.EmployeeId == item.Id && m.ShiftDate == item.Entry_Date).FirstOrDefault()
        if (shiftDetails != null)
        {
            //Other Calculations    
        }
    }
    

    接下来,您似乎正在做某种加入,最好看看是什么组成了data,这样我们就可以进一步提出一种显着改善时间的方法。

    这可能会给您带来一些改进:

    var query =
    (
        from a in ctx.tblEmployee.Where(x => x.CompanyId == companyId)
        join b in ctx.tblTO_Entry.Where(x => x.CompanyId == companyId) on a.Id equals b.EmployeeId
        where b.Entry_Date >= fromDate
        where b.Entry_Date <= toDate
        join m in ctx.tblTO_ShiftSchedule.Where(x => x.CompanyId == companyId) on new
        {
            a.Id,
            b.Entry_Date
        } equals new
        {
            Id = m.EmployeeId,
            Entry_Date = m.ShiftDate
        } into g
        from m2 in g.Where(x => x.ShiftDate >= fromDate).Where(x => x.ShiftDate <= toDate).Take(1)
        select m2
    ).ToList();
    
    foreach (var shiftDetails in query)
    {
        //Other Calculations   
    }
    

    【讨论】:

    • 必须是从 op 过去的副本,但要在最右边才能引起注意。或者它是剩余的,因为 Op 做了一个选择但没有显示它的细节。
    • 但是如果不需要 select,它应该被移除,因为 Select 将需要 where select 可枚举迭代器的另一个实例。性能增益很小。
    猜你喜欢
    • 2017-04-11
    • 2023-03-30
    • 2015-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-08
    • 2018-11-09
    • 1970-01-01
    相关资源
    最近更新 更多