2017-04-23 11 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(); 

私は県や市と同じであるオブジェクトのリストのリストを取得しようとしています。しかし、2番目のクエリは結果を出すのに時間がかかりすぎます。私は約30分待ったが答えは無かったが、リストDataには約5000件のレコードがある。これらのクエリを変更して、私が望むリストのリストを取得する方法はありますか?前もって感謝します。

リスト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 = 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 } 

が、私はこのようないくつかのリストにこのリストを作りたい:

は、たとえば次のクエリは、このようなリストを返します。

{ 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())を使用できません。 – Biswabid

+0

@Biswabidいいえ私は自分自身をよく説明できないと思う。私の編集を見てください。 – jason

+0

これは私がlinqを好きではない理由です。あなたはそれがどのように動作するか分からなければ、ひどいことがあります。呼び出す各メソッドは、別のIEnumerableを返すIEnumerableでforeachを実行します。だから、これらの連鎖呼び出しはすべてスタックアップしているかもしれません。おそらく10回、15回のループをしています。あなたが独自のコードでlinqではなく単一の関数として書き直すと、パフォーマンスが向上することがわかります – peteisace

答えて

1

可能性1:あなたのデータベースはあなたのクエリをサポートするために索引付けされていないに(どこで、句に参加)。

確認するには、生成されたSQLを取得し、実行計画を確認します。プランにネストループ結合 - >クラスタード・インデックス・スキャンが表示されている場合は、問題が見つかりました。

可能性2:n + 1の問題が見つかりました。

LinqのGROUP BYでは、グループはグループキーとグループメンバーで構成されています。しかし、ほとんどのSQL実装では、GROUP BYはグループ鍵と集約を提供します。グループのメンバーを取得するために、別のクエリが発行されます。 n個のグループがある場合は、n個のクエリを発行する必要があります(+1は元のクエリです)。

確認するには、生成されたSQLを取得します。余分なクエリが発行されていて、クラスタ化されたインデックススキャンと言っている人は、この問題を発見しました。

可能性3:実際にn^2(〜5,000,000)のクエリを発行しています。

まあ、あなたは2度にグループ分けされているので、2重に入れ子になったループかもしれません。生成されたSQLを見て、見つけてください。


これの最も単純な修正は、グループ化する前に5,000レコードをメモリにプルすることです。これを行う簡単な方法は、GroupByを呼び出す前にToListに電話することです。

+0

このような詳細な回答ありがとうございます。 'GroupBy'の前に' ToList'を呼び出すと、ゼロの答えが返されます。 – jason

関連する問題