Linq 性能:从查询中移出条件是否有意义

本文关键字:移出 条件 是否 有意义 查询 性能 Linq | 更新日期: 2023-09-27 18:31:54

有一个 LINQ 查询:

int criteria = GetCriteria();
var teams = Team.GetTeams()
    .Where(team=> criteria == 0 || team.Criteria == criteria)
    .ToList();

从性能(或任何其他角度)将其转换为以下内容是否有意义?

var teams = Team.GetTeams();
if (criteria != 0)
{
    teams = teams.Where(team => team.Criteria == criteria);
}
teams = teams.ToList();

有一套坚实的标准;我是否应该将它们分开并仅在必要时应用每个标准?或者只在一个 LINQ 查询中应用它们,而让 .NET 来优化查询?

请指教。欢迎任何想法!

附言:伙计们,我不使用 Linq2Sql,只使用 LINQ,这是一个纯 C# 代码

Linq 性能:从查询中移出条件是否有意义

首先,重要的是要了解 LINQ 实际上有几个变体,这些变体主要可以通过它们是使用表达式树还是编译代码来执行查询来划分。

Linq2Sql(以及将查询转换为另一种形式以执行查询的任何 Linq 提供程序)使用表达式树,以便可以分析查询并将其转换为另一种形式(通常是 SQL)。在这种情况下,提供程序可以修改查询,从而可能执行某种级别的优化。我不知道目前有任何提供商这样做。

Linq to Objects 使用已编译的代码,并将始终按编写的方式执行查询。除了开发人员之外,没有机会优化查询。

其次,所有 Linq 查询都将延迟。这意味着在尝试获取结果之前,查询不会实际执行。这样做的副作用是,您可以通过多个步骤构建查询,并且只会执行最终查询。问题中的第二个示例仍然导致只执行一个查询

如果您使用的是 Linq2Sql,则两个查询的性能可能大致相似。但是,扩展为处理许多标准的第一个示例可能会导致过于通用的执行计划不佳,最终会降低性能。修剪后的查询不会运行此风险,并且会为每个条件的实际排列生成执行计划。

如果使用 Linq to Objects,则第二个查询绝对更可取,因为第一个查询将为每个输入执行一次传递给 Where 的谓词,即使条件始终返回 true。

我认为第二个选项更好,因为它只检查一次条件值。而在第一个查询中,正在检查每一行的条件。
但我也相信你不会从中获得任何显着的性能提升。它可能会在具有大量记录的表上为您提供更好的结果(理论上)