有没有办法分析特定的Linq-to-objects查询将如何执行?

时间:2009-10-27 14:26:14

标签: linq performance linq-to-objects

过去,我已经将Linq写入了SQL查询,这些查询效果不佳。使用SQL事件探查器(或类似)我可以通过在数据库中拦截我的查询来查看我的查询是如何转换为SQL的。

有没有办法使用仅针对对象运行的Linq查询?

例如,在有向图中的边列表上考虑以下Linq查询:

var outEdges = from e in Edges
               where e.StartNode.Equals(currentNode) &&
               !(from d in deadEdges select d.StartNode).Contains(e.EndNode)
               select e;

该代码应该选择从当前节点开始的所有边,除了那些可能导致死边的边。

现在,我怀疑这段代码是低效的,但我不知道除了分析生成的MSIL之外如何证明它。我宁愿不这样做。

有没有人知道如何在没有SQL的情况下做到这一点?

修改

当我谈论低效率时,我的意思是“大O”符号或渐近符号的低效率。在上面的例子中,代码是以O(n)还是O(n log m)甚至O(n.m)执行Linq?换句话说,执行路径的复杂性是什么?

使用Linq to SQL,我可能会看到(例如)第二个where子句被转换为为每个边运行的子查询,而不是更有效的连接。在这种情况下我可能决定不使用Linq,或者至少更改Linq,因此对于大型数据集来说它更有效。

编辑2:

Found this post - 我不知道我是如何错过它的。只是在寻找错误的东西我想:)

1 个答案:

答案 0 :(得分:1)

我不认为你需要一个探查器......

Linq to SQL(或Linq to Entities)查询被翻译成另一种语言(SQL),然后使用优化的执行计划执行,因此很难看出究竟发生了什么;对于这种情况,分析器可能会有所帮助。另一方面,Linq to Objects查询未翻译,它们按“原样”执行。使用类SQL语法的Linq to Objects查询只是一系列方法调用的语法糖。在您的情况下,查询的完整形式将是:

var outEdges = Edges.Where(e => e.StartNode.Equals(currentNode) &&
                           !deadEdges.Select(d => d.StartNode).Contains(e.EndNode));

所以,基本上,你迭代Edges,对于Edges中的每个项目,你都会迭代deadEdges。因此,此处的复杂性为O(n.m),其中nEdges中的项目数,m deadEdges中的项目数