2010-08-05 70 views
1

我有一个非常简单的SortedSet,它有一个基于两个类字段排序的CompareTo方法。就像它被使用的那样,这个集合可以获得相当大的(百万以上的对象),并随着时间的推移而增长和增长。我一直在使用一个简单的Contains方法来确定一个新的值是否已经存在于集合中...SortedSet <T> Contains vs Linq查询

作为一个学术练习,我正在使用Linq(我很新)来达到同样的效果并且肯定我对Linq有一些了解,我缺乏,因为我无法远程接近相同的表现,而且我想知道是否一些Linq大师能够给我一个关于如何加快速度的指示。

所以...对象具有的CompareTo看起来是这样的:

public int CompareTo(EntityHistoryChange other) 
{ 
    int recordIdComp = Recordid.CompareTo(other.Recordid); 
    int tableIdComp = Tablename.CompareTo(other.Tablename); 

    if (recordIdComp == 0 && tableIdComp == 0) 
     return 0; 
    else if (recordIdComp != 0) 
     return recordIdComp; 
    else 
     return tableIdComp; 
} 

上简单的列表中的相应Linq查询:

var handledChange = from thisChange in handledChanges 
        where thisChange.Recordid == recordId 
         && thisChange.Tablename == tableName 
        select thisChange; 

我想结果应该不会让我感到吃惊。 ..

Linq Lookup on 18772 rows: 46 ms 
SortSet Lookup on 18772 rows: 3 ms 

所以问题是 - 什么是等效的LINQ机制?

+0

考虑到Linq增加的抽象层,这看起来很不错。 – 2010-08-05 17:04:57

回答

0

许多LINQ运营商检查IEnumerable<T>以外的接口并利用它们。

E.g. Count将检查ICollection<T>并使用其Count属性而不是遍历整个集合。看到这些(基准测试之外)的唯一方法是查看IL(或使用Refector),当然实现可能会随新的.NET版本(包括SP)而改变。例如。在.NET 5款Count没有检查ICollection,但在4

2

的LINQ确实决不会以最快的速度,因为那个LINQ的看到的不是SortedSet的对象,但IEnumerable<T>,它没有语义除了“给我一个对象列表”之外。你根本没有利用Set'ness。

什么关键是SortedSet<T>排序?这不是通过SortedSet.Contains查找,那么你可以检查表名?

0

LINQ并不是要取代给定作业的正确数据结构的使用。它只是简化了处理这些数据结构。如果您将数据存储在SQL数据库中,则仍需要在数据库上使用智能索引来提高性能。同样,在LINQ to Objects的情况下,您需要在适当的地方使用像SortedSet<T>这样的数据结构。

所以回答你的问题是:LINQ查询,模拟包含的方法是:

var exists = handledChanges.Any(c => c.Recordid = recordId && c.Tablename == tableName); 

但是如果你使用LINQ to对象,这将永远不会实现相同的性能,使用包含特别定制的快速查找数据结构的方法。如果您使用LINQ to SQL或LINQ to Entities,这将提供优化的SQL查询,该查询可以非常快地运行。顺便说一下,如果您的目标是在内存集合上获得更快的查找,您可能需要考虑使用带有自定义IEqualityComparer的HashSet。它的Contains方法在收集数以百万计的对象时会占用很多时间,就像收集10个对象一样。