在实体中查找对象和加载实体、Foreach 或在哪里使用 LinQ ON C# 的最佳性能?
Posted
技术标签:
【中文标题】在实体中查找对象和加载实体、Foreach 或在哪里使用 LinQ ON C# 的最佳性能?【英文标题】:Best performance for find objects in entities and load entities, Foreach or where with LinQ ON C#? 【发布时间】:2017-01-21 05:40:38 【问题描述】:我需要关联一些实体。现在代码加载第一个实体,然后使用 foreach 循环进行迭代,如果当前行与另一个实体的记录的属性匹配,则搜索每条记录。 比如:
foreach (Entity1 e1 in entity1List)
foreach (Entity2 e2 in entity2List)
if (e2.Id == e1.Id)
//Do something
但是实体有很多记录,性能并不好。 我想提高尝试使用 linQ 搜索记录的速度。
var list = entity2List.Where(e2 => entity1.Any(e1 => e1.Id == e2.Id));
foreach (Entity2 e2 in list )
//Do something
但我不知道这是否真的有助于性能。另外我想知道在这种情况下加载实体的最佳模型。请提供一些建议或阅读链接或用于比较执行时间的工具。
我为每个实体的加载器使用了很多连接,但它们是分开的,因为在其他情况下测试行很多,并且在数据库上执行查询的时间太多,所以现在实体是独立的,我想通过代码创建依赖项。
【问题讨论】:
您可以随时分析两者并找出答案。 (提示:加载更少的记录比加载更多的记录总是会带来净收益)。 您不使用连接的任何原因? 并从 List如果两个实体集都是真正的列表,则使用 LINQ Where
不会给您带来性能提升,因为它相当于您当前具有 O(M * N) 时间复杂度的线性搜索算法。
但是,您可以通过使用 LINQ GroupJoin
方法获得更好的 O(M + N) 时间复杂度算法(从而提高性能),该方法在内部使用非常有效的基于哈希的查找来关联两个序列:
var list = from e1 in entity1List
join e2 in entity2List on e1.Id equals e2.Id into e2Group
select new e1, e2Group ;
foreach (var item in list)
var e1 = item.e1;
foreach (var e2 in item.e2Group)
//Do something
如果您不需要嵌套的 foreach
循环进行处理,则可以使用 Join
代替,这样效率会更高:
var list = from e1 in entity1List
join e2 in entity2List on e1.Id equals e2.Id
select new e1, e2 ;
foreach (var item in list)
var e1 = item.e1;
var e2 = item.e2;
//Do something
【讨论】:
谢谢,我将我的方法的时间与 dotTrace 进行了比较,现在更好【参考方案2】:正如@DavidL 所说,您可能想测试这两种解决方案,看看会发生什么。另一种选择是使用第一个集合进行哈希,然后通过键搜索。它应该会影响性能。
例子:
var e1ById = entity1List.GroupBy(x => x.Id).ToDictionary(x => x.Key); //you can skip the GroupBy if you know Id is a unique key)
foreach(var e2 in entity2List.Where(x => e1ById.ContainsKey(e2.Id)))
//Do something
或者也许使用列表来存储密钥:
var keys = entity1List.Select(x => x.Id).Distinct().ToList();
foreach(var e2 in entity2List.Where(x => keys.Contains(x.Id))
//Do something
无论如何,性能取决于初始收集长度,因此请尝试不同的解决方案并记下时间。
【讨论】:
【参考方案3】:一般来说,如果性能是您的主要关注点,您通常最好编写自己的优化算法。由于开销,LINQ 肯定会比您的最佳算法慢。但是,LINQ 很优雅,对代码的可维护性非常有用。所以,选择权在你!
在这种特殊情况下,您可以使用 Intersect() 方法,该方法比您当前的实现更高效、更简单。
foreach (var element in entity1List.Intersect(entity2List))
// Do something
【讨论】:
以上是关于在实体中查找对象和加载实体、Foreach 或在哪里使用 LinQ ON C# 的最佳性能?的主要内容,如果未能解决你的问题,请参考以下文章