使用可枚举的linq从列表模型中获取模型的性能很慢

时间:2016-03-12 19:24:05

标签: c# performance linq ienumerable enumerable

我决定将数据库记录倒入List<>模型并使用可枚举的Linq从中获取记录。它有141,856条记录。我们发现的是它很慢。

那么,有关使其快速运行的任何建议或建议吗?

public class Geography
{
    public string Zipcode { get; set; }
    public string City { get; set; }
    public string State { get; set; }
}

var geography = new List<Geography>();

geography.Add(new Geography() { Zipcode = "32245", City = "Jacksonville", State = "Florida" });
geography.Add(new Geography() { Zipcode = "00001", City = "Atlanta", State = "Georgia" });

var result = geography.Where(x => (string.Equals(x.Zipcode, "32245", String Comparison.InvariantCulterIgnoreCase))).FirstOrDefault();

当我们在库存中有86,000辆车时,我们希望使用并行任务来快速完成,但是在查找地理位置时它变得非常慢。

await Task.WhenAll(vehicleInventoryRecords.Select(async inventory =>
{
    var result = geography.Where(x => (string.Equals(x.Zipcode, inventory.Zipcode, String Comparison.InvariantCulterIgnoreCase))).FirstOrDefault();

}));

2 个答案:

答案 0 :(得分:2)

使用dictionary<string, Geography>存储地理数据。按键查找字典中的数据是O(1)操作,而列表中的数据是O(n)

答案 1 :(得分:0)

你没有提到你的邮政编码是否是唯一的,所以我认为它们不是。如果是 - 请查看Giorgi's answer并跳到我的答案的第2部分。

<强> 1。使用查找

由于您要通过同一媒体资源多次查找geography列表,因此您应该按Zipcode对这些值进行分组。您可以使用ToLookup轻松完成此操作 - 这将创建一个Lookup对象。它类似于Dictionary,但它可以是多个值,因为它的值。将StringComparer.InvariantCultureIgnoreCase作为第二个参数传递给ToLookup会使其不区分大小写。

var geography = new List<Geography>();
geography.Add(new Geography { Zipcode = "32245", City = "Jacksonville", State = "Florida" });
geography.Add(new Geography { Zipcode = "00001", City = "Atlanta", State = "Georgia" });

var geographyLookup = geography.ToLookup(x => x.Zipcode, StringComparer.InvariantCultureIgnoreCase);
var result = geographyLookup["32245"].FirstOrDefault();

这会大大提高你的表现。

<强> 2。与PLINQ并行化

您对查找进行并行化的方式值得怀疑。幸运的是,.NET有PLINQ。您可以使用AsParallel和并行Select来异步迭代vehicleInventoryRecords,如下所示:

var results = vehicleInventoryRecords.AsParallel().Select(x => geographyLookup[x].FirstOrDefault());

使用Parallel.ForEach是另一个不错的选择。