Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用Linq对对象或使用本机SQL对内存中的数据进行分组--哪一种更快?_C#_.net_Sql_Group By - Fatal编程技术网

C# 使用Linq对对象或使用本机SQL对内存中的数据进行分组--哪一种更快?

C# 使用Linq对对象或使用本机SQL对内存中的数据进行分组--哪一种更快?,c#,.net,sql,group-by,C#,.net,Sql,Group By,我注意到linqto对象有一个GroupBy方法。有鉴于此,我想知道是否有人可以为使用LINQ对内存中的对象进行分组创建一个案例,而不是让SQL Server执行分组?在具有正确索引表的大型数据集上,SQL Server会更快。每一次。唾手可得地对于较小的数据集,您甚至可能没有注意到差异。您可能希望在客户端上使用LINQ进行分组的原因有: 您的对象已在内存中 您可能希望在数据生命周期中的不同时间按不同的键进行分组,返回数据库的代价可能会很高 您可能希望按SQL Server不方便计算的内容进行分

我注意到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秒
    生成的查询非常复杂,因此需要很长时间

    在.NET中分组

    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秒
    生成的SQL更简单、更快,但是C#计算稍微慢一点

    在.NET中分组,具有一些类似的风格

    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往返时间。