【问题标题】:Optimize this LINQ Query优化此 LINQ 查询
【发布时间】:2012-06-28 05:09:15
【问题描述】:

我在使用此 LINQ 查询时遇到性能问题。 数据已加载到 this.students 中。 现在,当我调用 GetStudentData 函数说 1000 次时,它会产生巨大的开销。 有没有办法在不将 LINQ 更改为循环的情况下改进这一点

   public Student GetStudentData()
   {         
          IEnumerable<Students> studentTypes = this.students.Where(x => (x.studentsId  == studentId && x.StduentType.Equals(studentType)));
          if(studentTypes.Count==0) return new Student() { studentid=studentID};
          return (Student)studentTypes.First();
   }

所以这里是使用我的原始版本循环 10000 次时的结果

原始版本:平均 5.6 秒 带有FirstOrDefault 的新版本@des 代码:3.6 秒

【问题讨论】:

  • 你真的在运行这 1000 个吗?否则,这篇文章非常合适:hanselman.com/blog/…
  • ew,顺便说一句,如果没有找到符合条件的学生,我真的不喜欢你如何返回新学生 - 非常混乱。
  • 是的,我正在运行 1000 次
  • IEnumerable&lt;Students&gt; 是错字吗?应该是IEnumerable&lt;Student&gt;
  • 是的,一定是错字。抱歉

标签: c# performance linq


【解决方案1】:

当您使用 Where 时,您会遍历满足给定条件的 所有 记录,当您使用 First 时,您只需搜索满足条件的 first 记录,因此使用First 应该会加快速度。

public Student GetStudentData()
{         
    // get first student by id and type, return null if there is no such student
    var student = students.FirstOrDefault(i => i.studentsId == studentId && i.StudentType.Equals(studentType));

    // if student is null then return new student
    return student ?? new Student();
}

【讨论】:

  • 这可能会简化代码,但那里没有优化
  • @ErOx 检查我更新的答案,First 应该比 Where 快,因为它不会检查所有记录...
  • 很好的解释...让我测试一下看看结果
  • 这是不对的。为什么你会认为 .First(anonymous-delegate) 和 Where(anonymous-delegate).First() 之间存在性能差异?您不认为 exact same 过滤器在这两种情况下都在运行吗?
  • 看看IL,我可以向你保证
【解决方案2】:

嗯,问题恰恰是你在一个循环中调用这个方法,据说是 1000 次!

为什么不改变方法来接收学生 ID 列表并一次性返回 1000 名学生?类似的东西

var studentTypes = from c in this.students 
                   where studentIDs.Contains(c.StudentID)
                   select c;

studentIDs 可以是 int[],其中包含您想要的学生 ID 列表。

【讨论】:

  • 我认为这是在正确的轨道上 - 看起来需要对 OP 的逻辑进行一些重构
  • Nopes...这是用不同的参数调用...这只是真实函数的一个更简单的版本...所以它很容易理解。
【解决方案3】:

重构您的代码,使this.studentsDictionary&lt;int, Student&gt;(键是StudentId),然后类似地重新实现您的方法:

public Student GetStudentData(int studentId, StudentType studentType) {
    Student result;
    if (this.students.TryGetValue(studentId, out result))
        if (result.StudentType.Equals(studentType)))
            return result;
    return new Student { StudentId = studentId };
}

如果你绝对不能重构this.students,你总是可以并行维护字典

或者,您可以在 1000 次迭代循环之前创建一个临时字典 (this.students.ToDictionary(student =&gt; student.StudentId))。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-15
    • 1970-01-01
    相关资源
    最近更新 更多