Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/332.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嵌套组性能_C#_Performance_Linq_Entity Framework_Grouping - Fatal编程技术网

C# LINQ嵌套组性能

C# LINQ嵌套组性能,c#,performance,linq,entity-framework,grouping,C#,Performance,Linq,Entity Framework,Grouping,我有一个从sql compact数据库提取数据的完整外部联接查询(我使用EF6进行映射): 如您所见,我使用嵌套组来构造结果。 有趣的是,如果我删除AsEnumerable()调用,查询执行时间将增加3.5倍:~210ms vs~60ms。当它第一次运行时,差异要大得多:39000(!)毫秒与13000毫秒 我的问题是: 我做错了什么,也许这些分组应该以不同的方式进行 为什么第一次执行要花这么多时间?我知道应该建立表达式树等等,但是39秒 在我的例子中,为什么linq到db比linq到实体慢?如

我有一个从sql compact数据库提取数据的完整外部联接查询(我使用EF6进行映射):

如您所见,我使用嵌套组来构造结果。 有趣的是,如果我删除AsEnumerable()调用,查询执行时间将增加3.5倍:~210ms vs~60ms。当它第一次运行时,差异要大得多:39000(!)毫秒与13000毫秒

我的问题是:

  • 我做错了什么,也许这些分组应该以不同的方式进行

  • 为什么第一次执行要花这么多时间?我知道应该建立表达式树等等,但是39秒

  • 在我的例子中,为什么linq到db比linq到实体慢?如果可能的话,在处理之前从数据库加载数据是否通常比较慢和更好

  • 萨克斯

    使用
    AsEnumerable()
    将实现
    IEnumerable
    的类型转换为
    IEnumerable
    本身

    阅读本主题

    当序列实现
    IEnumerable
    时,可以使用
    AsEnumerable(IEnumerable)
    在查询实现之间进行选择,但也有一组不同的公共查询方法可用。例如,给定一个通用类
    Table
    ,该类实现了
    IEnumerable
    ,并具有自己的方法,如
    Where
    Select
    、和
    SelectMany
    ,调用
    Where
    将调用
    Table
    的public
    Where
    方法。表示数据库表的
    Table
    类型可以有一个
    Where
    方法,该方法将谓词参数作为表达式树,并将树转换为SQL以供远程执行。如果不需要远程执行,例如因为谓词调用本地方法,则可以使用
    AsEnumerable
    方法隐藏自定义方法,而不是使标准查询运算符可用


    首先调用
    AsEnumerable()
    时,它不会将LINQ转换为SQL,而是在
    枚举表时将表加载到内存中。因为现在它被加载到内存中,所以执行速度更快

    要回答您的三个问题:

    也许这些分组应该以不同的方式进行

    不需要。如果需要嵌套分组,则只能通过分组中的分组来实现

    您可以一次按多个字段分组:

    from entry in left.Union(right)
    select new
    {
        ...
    } into e
    group e by new 
               { 
                   e.Date.Year, 
                   Quartal = (e.Date.Month - 1) / 3 + 1, 
                   e.Date.Month, 
                   contract = e.Contract.extNo 
               } into grp
    select new
    {
        Year = grp.Key,
        Quartal = grp.Key,
        Month = grp.Key,
        Contracts = from x in grp
                    select new
                    {
                        ExtNo = month.Key,
                        Entries = contract,
                    }
    }
    
    这将从生成的查询中删除大量复杂性,因此,如果不使用
    AsEnumerable()
    ,查询速度可能会(快得多)。但结果却大不相同:一个扁平的组(一行中的年份、四分之一等),而不是嵌套的组

  • 为什么第一次执行要花这么多时间
  • 因为生成的SQL查询可能非常复杂,数据库引擎的查询优化器无法找到快速执行路径

    3a。在我的例子中,为什么linq到db比linq到实体慢

    因为,显然,在这种情况下,首先将数据提取到内存中,然后通过LINQ对对象进行分组要高效得多。如果
    left
    right
    表示或多或少复杂的查询,这种影响将更为显著。在这种情况下,生成的SQL可能会变得非常臃肿,因为它必须在一条语句中处理两个复杂源,这可能会导致许多重复的相同子查询。通过外包分组,数据库可能只剩下一个相对简单的查询,当然,内存中的分组永远不会受到SQL查询复杂性的影响

    3b。如果可能的话,在处理之前从数据库加载数据是否通常比较慢和更好

    不,不一般。我甚至会说,几乎从来没有。在这种情况下,这是因为(正如我所看到的)您不过滤数据。但是,如果
    aseneumerable()
    之前的部分返回数百万条记录,然后应用过滤,那么不使用
    aseneumerable()
    的查询可能会快得多,因为过滤是在数据库中完成的


    因此,您应该始终关注生成的SQL。期望EF总是生成一个超级优化的SQL语句是不现实的。它几乎永远不会。它的主要关注点是正确性(它在这方面做得非常出色),性能是次要的。开发人员的工作是使LINQ to实体和LINQ to对象作为一个灵活的团队一起工作。

    可计算的
    在分组之前将数据放入内存。删除它意味着要对数据库运行多个子查询,这会导致数据库运行速度变慢。顺便说一下,下次,最好一次只问一个问题。StackOverflow喜欢用一个答案可能会冒泡出来作为答案的方式回答问题。如果有三个人回答你的三个问题,那就很难了。
    
    from entry in left.Union(right)
    select new
    {
        ...
    } into e
    group e by new 
               { 
                   e.Date.Year, 
                   Quartal = (e.Date.Month - 1) / 3 + 1, 
                   e.Date.Month, 
                   contract = e.Contract.extNo 
               } into grp
    select new
    {
        Year = grp.Key,
        Quartal = grp.Key,
        Month = grp.Key,
        Contracts = from x in grp
                    select new
                    {
                        ExtNo = month.Key,
                        Entries = contract,
                    }
    }