2017-04-23 85 views
0

我有这些疑问:为什么Double GroupBy + ToList耗时过长?

var Data = (from ftr in db.TB_FTR 
         join mst in db.TB_MST on ftr.MST_ID equals mst.MST_ID 
         join trf in db.TB_TRF on mst.TRF_ID equals trf.ID 
         select new CityCountyType { City = ftr.CITY, County = ftr.COUNTY, Type = trf.TYPE } 
        ).OrderBy(i => i.City).ThenBy(i => i.County); 

var Data2 = 
    Data.GroupBy(i => new {i.City, i.County, i.Type}) 
     .Select(group => new {Name = group.Key, Count = group.Count()}) 
     .OrderBy(x => x.Name) 
     .ThenByDescending(x => x.Count) 
     .GroupBy(g => new {g.Name.City, g.Name.County}) 
     .Select(g => g.Select(g2 => 
      new {Name = new {g.Key.City, g.Key.County, g2.Name.Type}, g2.Count})).ToList(); 

我试图让对象,它们的县市是相同的列表清单。但是第二个查询花费太长时间才能得出结果。我等了大约30分钟,但没有回答,但是名单Data有大约5000条记录。如何更改这些查询以便我可以获取我想要的列表清单?提前致谢。

例如该查询返回这样一个列表:

{ Name = {{ City = New York City, County = Bronx, Type = Type A }}, Count = 4 } 

{ Name = {{ City = New York City, County = Bronx, Type = Type B }}, Count = 8 } 

{ Name = {{ City = New York City, County = Bronx, Type = Type C }}, Count = 24 } 

{ Name = {{ City = New York City, County = Manhattan, Type = Type B }}, Count = 43 } 

{ Name = {{ City = New York City, County = Manhattan, Type = Type C }}, Count = 58 } 

{ Name = {{ City = Seattle, County = King County, Type = Type D }}, Count = 43 } 

{ Name = {{ City = Seattle, County = King County, Type = Type A }}, Count = 67 } 

{ Name = {{ City = Seattle, County = Snohomish County, Type = Type C }}, Count = 67 } 

我想使这个名单几个列表如下:

表1:

{ Name = {{ City = New York City, County = Bronx, Type = Type A }}, Count = 4 } 

{ Name = {{ City = New York City, County = Bronx, Type = Type B }}, Count = 8 } 

{ Name = {{ City = New York City, County = Bronx, Type = Type C }}, Count = 24 } 

表2:

{ Name = {{ City = New York City, County = Manhattan, Type = Type B }}, Count = 43 } 

{ Name = {{ City = New York City, County = Manhattan, Type = Type C }}, Count = 58 } 

列表3:

{ Name = {{ City = Seattle, County = King County, Type = Type D }}, Count = 43 } 

{ Name = {{ City = Seattle, County = King County, Type = Type A }}, Count = 67 } 

表4:

{ Name = {{ City = Seattle, County = Snohomish County, Type = Type C }}, Count = 67 } 
+0

不能使用Data.Where(a => a.City.ToString()== a.County.ToString())。select(a); – Biswabid

+0

@Biswabid不,我认为我不能很好地解释自己。请参阅我的编辑。 – jason

+0

这就是为什么我不喜欢linq。如果你不明白它是如何工作的,那可能会很糟糕。您调用的每种方法都会通过IEnumerable返回另一个IEnumerable。所以这些链接的电话都堆叠起来,你可能会做十个,十五个循环。如果你使用自己的代码而不是linq来重写单一函数,你会看到性能提高 – peteisace

回答

1

可能性1:您的数据库没有被索引,以支持您的查询(其中,并加入条款)。

为了弄清楚,获取生成的sql并查看执行计划。如果该计划显示嵌套循环连接 - >聚集索引扫描,则发现问题。

可能性2:您发现了n + 1问题。

在Linq的GROUP BY中,一个组由组密钥和组成员组成。但是在大多数SQL实现中,GROUP BY为您提供组密钥和聚合。为了获得一个组的成员,发出一个单独的查询。如果有n个组,则必须发出n个查询(+1是原始查询)。

为了弄清楚,得到生成的sql。如果发布了一堆额外的查询,并且其中任何一个都说聚簇索引扫描,那么你就发现了这个问题。

可能性3:您实际上正在发出n^2(〜5,000,000)个查询。

那么,你分组了两次,所以它可能是一个双重嵌套的循环。看看生成的SQL并找出答案。


最简单的解决方法就是在分组之前将5,000条记录拉入内存。一个简单的方法是在致电GroupBy之前致电ToList

+0

谢谢你这样一个详细的答案。当我在'GroupBy'之前调用'ToList'时,它会给出零答案。 – jason

相关问题