C# 使用Linq对对象或使用本机SQL对内存中的数据进行分组--哪一种更快?
我注意到linqto对象有一个GroupBy方法。有鉴于此,我想知道是否有人可以为使用LINQ对内存中的对象进行分组创建一个案例,而不是让SQL Server执行分组?在具有正确索引表的大型数据集上,SQL Server会更快。每一次。唾手可得地对于较小的数据集,您甚至可能没有注意到差异。您可能希望在客户端上使用LINQ进行分组的原因有:C# 使用Linq对对象或使用本机SQL对内存中的数据进行分组--哪一种更快?,c#,.net,sql,group-by,C#,.net,Sql,Group By,我注意到linqto对象有一个GroupBy方法。有鉴于此,我想知道是否有人可以为使用LINQ对内存中的对象进行分组创建一个案例,而不是让SQL Server执行分组?在具有正确索引表的大型数据集上,SQL Server会更快。每一次。唾手可得地对于较小的数据集,您甚至可能没有注意到差异。您可能希望在客户端上使用LINQ进行分组的原因有: 您的对象已在内存中 您可能希望在数据生命周期中的不同时间按不同的键进行分组,返回数据库的代价可能会很高 您可能希望按SQL Server不方便计算的内容进行分
data.GroupBy(d=>DoSomethingComplicatedWith(d))
如果您处理的是一小部分数据,那么客户机上的性能就不成问题,并且再次返回数据库以将数据转换为您想要的格式不是一个选项(或一个不需要的选项),那么在内存中执行就可以了
在所有其他情况下,您最好的选择是让数据库完成这项工作,因为它正是针对这种操作而优化的。有(不是太少)情况下,您的对象不包含在数据库中。如前所述,选择分组客户端(C#)与服务器端可能有几个原因(SQL Server)。我决定做一个小测试-下面的查询应该决定特定计算中缺少哪些文章和用户对 查询返回大约150万条记录,这些记录分为15000多个组 在SQL中分组
allArticleConcepts = DataAccess.ArticleConceptRepository.AllNoTracking
.Join(DataAccess.ArticleAnalysisDataRepository.AllNoTracking.Where(aa => aa.CommentCount >= minCommentCount),
outer => outer.ArticleId,
inner => inner.ArticleId,
(outer, inner) => outer)
.Where(ac => missingXData.Any(x => x.ArticleId == ac.ArticleId))
.GroupBy(ac => ac.ArticleId)
.ToDictionary(grp => grp.Key, grp => grp
.Select(ac => new Concept { ContextSynLexemId = ac.LexemId, LexemId = ac.LexemId, Frequency = ac.Freq })
.ToList());
- SQL持续时间=22秒
- 总持续时间=23秒
allArticleConcepts = DataAccess.ArticleConceptRepository.AllNoTracking
.Join(DataAccess.ArticleAnalysisDataRepository.AllNoTracking.Where(aa => aa.CommentCount >= minCommentCount),
outer => outer.ArticleId,
inner => inner.ArticleId,
(outer, inner) => outer)
.Where(ac => missingXData.Any(x => x.ArticleId == ac.ArticleId))
.ToList()
.GroupBy(ac => ac.ArticleId)
.ToDictionary(grp => grp.Key, grp => grp
.Select(ac => new Concept { ContextSynLexemId = ac.LexemId, LexemId = ac.LexemId, Frequency = ac.Freq })
.ToList());
- SQL持续时间=13秒
- 总持续时间=15秒
allArticleConcepts = DataAccess.ArticleConceptRepository.AllNoTracking
.Join(DataAccess.ArticleAnalysisDataRepository.AllNoTracking.Where(aa => aa.CommentCount >= minCommentCount),
outer => outer.ArticleId,
inner => inner.ArticleId,
(outer, inner) => outer)
.Where(ac => missingXData.Any(x => x.ArticleId == ac.ArticleId))
.ToList()
.AsParallel()
.GroupBy(ac => ac.ArticleId)
.ToDictionary(grp => grp.Key, grp => grp
.Select(ac => new Concept { ContextSynLexemId = ac.LexemId, LexemId = ac.LexemId, Frequency = ac.Freq })
.ToList());
这在客户端提供了一个小的改进
作为如何进行分组的结论:
- 如果无法将逻辑转换为SQL:LINQ2对象是必须的
- 如果逻辑相当复杂和/或处理大量实体,那么LINQ2对象最有可能是解决方法
- 如果逻辑非常简单,并且可以使用索引,那么Linq2SQL很可能是最好的选择。然而,这也需要仔细编写LINQ,以避免生成低效的查询
注释:如果查询处理大量实体,但结果相对较小,则可以考虑直接查询执行(或存储过程)并将结果映射到实体,这确保了最大限度地编写查询的灵活性,并最小化了C.SQ-SQLServer往返时间。