Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/75.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 Multiple GroupBy查询的执行速度比T-SQL慢几倍_C#_Sql_Performance_Linq_Group By - Fatal编程技术网

C# LINQ Multiple GroupBy查询的执行速度比T-SQL慢几倍

C# LINQ Multiple GroupBy查询的执行速度比T-SQL慢几倍,c#,sql,performance,linq,group-by,C#,Sql,Performance,Linq,Group By,我对林克完全是新手 我有一个sqlgroupby,它只运行了几毫秒。但当我试图通过LINQ实现同样的目标时,它似乎太慢了。 我试图实现的是获取ceratin数据库更新的平均每月持续时间 在SQL中=> select SUBSTRING(yyyyMMdd, 0,7), AVG (duration) from (select (CONVERT(CHAR(8), mmud.logDateTime, 112)) as yyyyMMdd, DateD

我对林克完全是新手

我有一个
sqlgroupby
,它只运行了几毫秒。但当我试图通过LINQ实现同样的目标时,它似乎太慢了。 我试图实现的是获取ceratin数据库更新的平均每月持续时间

在SQL中=>

select SUBSTRING(yyyyMMdd, 0,7), 
       AVG (duration) 
  from (select (CONVERT(CHAR(8), mmud.logDateTime, 112)) as yyyyMMdd, 
                DateDIFF(ms, min(mmud.logDateTime), max(mmud.logDateTime)) as duration
          from mydb.mydbo.updateData mmud
          left 
          join mydb.mydbo.updateDataKeyValue mmudkv
            on mmud.updateDataid = mmudkv.updateDataId
          left 
          join mydb.mydbo.updateDataDetailKey mmuddk
            on mmudkv.updateDataDetailKeyid = mmuddk.Id
         where dbname = 'MY_NEW_DB'
           and mmudkv.value in ('start', 'finish')             
         group
            by (CONVERT(CHAR(8), mmud.logDateTime, 112))
        ) as resultSet
  group 
     by substring(yyyyMMdd, 0,7)
  order
     by substring(yyyyMMdd, 0,7)
在LINQ=>中,我首先从链接数据库名称和UpdateData信息的表中获取记录,然后对相关信息进行筛选和分组

    entry.updatedata.Where(
        ue => ue.updatedataKeyValue.Any(
                  uedkv =>
                  uedkv.Value.ToLower() == "starting update" ||
                  uedkv.Value.ToLower() == "client release"))
         .Select(
             ue =>
             new
                 {
                     logDateTimeyyyyMMdd = ue.logDateTime.Date,
                     logDateTime = ue.logDateTime
                 })
         .GroupBy(
             updateDataDetail => updateDataDetail.logDateTimeyyyyMMdd)
         .Select(
             groupedupdatedata => new
                 {
                     UpdateDateyyyyMM = groupedupdatedata.Key.ToString("yyyyMMdd"),
                     Duration =
                                        (groupedupdatedata.Max(groupMember => groupMember.logDateTime) -
                                         groupedupdatedata.Min(groupMember => groupMember.logDateTime)
                                        )
                                        .TotalMilliseconds
                 }
        ).
          ToList();
var updatedataMonthlyDurations =
    updatedataInDateRangeWithDescriptions.GroupBy(ue => ue.UpdateDateyyyyMM.Substring(0,6))
                                           .Select(
                                               group =>
                                               new updatedataMonthlyAverageDuration
                                                   {
                                                       DbName = entry.DbName,
                                                       UpdateDateyyyyMM = group.Key.Substring(0,6),
                                                       Duration =
                                                           group.Average(
                                                               gmember =>
                                                               (gmember.Duration))
                                                   }
        ).ToList();
我知道LINQ中的GroupBy与t-SQL中的GroupBy不同,但不确定幕后会发生什么。当我运行LINQ版本时,有人能解释一下区别和内存中发生了什么吗?在我做了.ToList()之后,在第一次GroupBy之后,事情变得更快了。但即便如此,这种寻找平均持续时间的方法也非常缓慢。
使用Visual Studio 2012改进慢LINQ语句的最佳选择是什么?有什么方法可以改进慢LINQ语句?

您的LINQ查询在
LINQ to objects
中完成大部分工作。您应该构建一个
linqtoentities/sql
查询,该查询一次生成完整的查询

您的查询似乎有一个冗余的GROUPBY子句,我不确定哪个表
dbname
来自哪个表,但是下面的查询应该会让您走上正确的轨道

var query = from mmud in context.updateData 
            from mmudkv in context.updateDataKeyValue
                                  .Where(x => mmud.updateDataid == x.updateDataId)
                                  .DefaultIfEmpty()
            from mmuddk in context.updateDataDetailKey 
                                  .Where(x => mmudkv.updateDataDetailKeyid == x.Id)
                                  .DefaultIfEmpty()
            where mmud.dbname == "MY_NEW_DB"
            where mmudkv.value == "start" ||  mmudkv.value == "finish"
            group mmud by mmud.logDateTime.Date into g
            select new 
            {
               Date = g.Key,
               Average = EntityFunctions.DiffMilliseconds(g.Max(x => x.logDateTime), g.Min(x => x.logDateTime)),
            };

var queryByMonth = from x in query
                   group x by new { x.Date.Year, x.Date.Month } into x
                   select new
                   {
                     Year = x.Key.Year,
                     Month = x.Key.Month,
                     Average = x.Average(y => y.Average)
                   };

// Single sql statement is to sent to your database
var result = queryByMonth.ToList();

如果您仍然有问题,我们需要知道您是在使用entityframework还是LINQtoSQL。您需要提供您的上下文/模型信息

您应该检查生成的SQL的外观。谢谢@MarcinJuraszek。我检查了一下,结果完全不是我想象的那样。感谢LINQPad。您的linq将为我提供平均每天的持续时间。我想要每月一次。这就是为什么我有额外的groupby。我只是在学林克。所以我不知道你提到的术语=>linq->entities/linq->objects。现在用谷歌搜索它。我将尝试稍微改变一下我的方法并进行测试。谢谢你的小费。我会让你知道我的测试进展如何。对Linq to Entities有一点了解。我检查了我使用LinqPad编写的LINQ语句的SQL,似乎有100条SQL语句是在幕后为它创建的。所以我想我必须使用你给出的表达式来显式地连接实体。现在就开始测试。@eakangoplakrishnan-我把答案改成了每月平均数。非常感谢你为我指明了正确的方向。我花了一段时间。但是LinqToSql不理解某些事情,比如持续时间(datetime-datetime),它也不直接理解日期部分。但是在System.Data.Objects.SqlClient.SqlFunctions中的一些函数的帮助下,我成功地获得了所需的结果。你太棒了。虽然你的答案并不准确,但它仍然帮助我达到了目的,所以我接受它作为答案。