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

时间:2012-04-23 04:54:09

标签: c# .net performance linq linq-to-objects

有一个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以优化查询?

请指教。欢迎任何想法!

P.S。伙计们,我不使用Linq2Sql,只使用LINQ,这是一个纯粹的C#代码

2 个答案:

答案 0 :(得分:5)

首先,重要的是要理解LINQ实际上有多种类型,主要可以分为是否使用表达式树或编译代码来执行查询。

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

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

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

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

如果你正在使用Linq to Objects,那么第二个查询肯定是可取的,因为第一个查询将执行为每个输入传递给Where的谓词,即使条件总是返回true。

答案 1 :(得分:3)

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