【发布时间】:2013-01-18 11:10:59
【问题描述】:
假设我们有一个已排序的集合,例如 SortedSet 或 SortedList,其中包含许多 (10M+) 个元素。正在发生大量查询,因此性能很重要。从运行时比较来看,我的印象是 LINQ to Objects 没有利用排序,因此没有利用潜在的性能提升。
第一个例子 - 计算一个范围内的元素:
var mySortedSet1 = new SortedSet<int>();
// populate ...
int rangeCount = (from n in mySortedSet1
where ((n >= 1000000000) && (n <= 2000000000))
select n).Count();
不完全确定 LINQ to Objects 在内部做了什么,最坏的情况是检查每个 O(n) 的元素。通过利用 O(log n) 中的下限和上限进行二分搜索的排序,可以更快地完成。
第二个例子 - SelectMany 在集合列表中:
var myListOfSortedSets = new List<SortedSet<int>>();
// populate...
var q = myListOfSortedSets.SelectMany(s => s).OrderBy(s => s);
foreach (var n in q)
{
Console.WriteLine(n);
}
如果 LINQ to SQL 对象要利用排序,它可以在 O(n) 中有效地将所有排序集压缩合并到一个大的排序列表中。结果上的 .OrderBy 然后可以被忽略,因为列表已经排序。
相反,SelectMany 将所有已排序的集合连接到一个大的(现在未排序的)列表中,这将需要另一个 O(n log n) 排序。这可以通过删除 .OrderBy 并观察元素写入控制台的顺序来轻松验证。
我的问题是:是否已经有另一种更有效的 LINQ to SortedSet/SortedList 实现?
i4o 看起来很有趣,但似乎需要二级索引集合来提高对原始集合的查询性能。我只是希望通过利用排序来更快地对排序集合进行查询。
【问题讨论】:
-
Linq 中的 Where 方法对每个元素进行对象检查。所以在这种情况下使用 SortedList 并没有性能提升。
-
您到底想做什么查询?因为断言“LINQ 很愚蠢”并没有真正的用处……
-
上面的例子对于我想要运行的查询来说是非常典型的。我敢肯定还有更多的实例,LINQ to Objects 可以使用排序但不使用,例如找到最小值/最大值,所以我的问题是是否已经有一个用于排序集合的通用 LINQ 提供程序。
-
好问题!我想知道如何实现这样的提供者。我会调查的。
-
这并没有回答上述问题,但是既然您使用的是
SortedSet,为什么不明确使用它提供的方法而不是依靠 LINQ 来尝试做最好的事情呢?例如,对于您的第一个示例,int rangeCount = mySortedSet1.GetViewBetween(1000000000, 2000000000).Count;总是会更快,无论 LINQ 多么优化。
标签: .net linq linq-to-objects sortedlist sortedset