使用可枚举 linq 从列表模型获取模型时性能降低



我决定将数据库记录倒入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();
}));

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

你没有提到你的邮政编码是否是唯一的,所以我假设它们不是。如果是 - 看看Giorgi的答案并跳到我答案的第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. 与普林克并行化

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

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

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

最新更新