2017-05-06 18 views
0

私は約1 500 000のエンティティを持つMySQLデータベースを持っています。私はEFコア1.1とMysql.Data.EntityFrameworkCore 7.0.7-M61はそれを仕上げるのに約40分かかります使用して文の下に実行しようとすると:ローカルのmysql-CLIとステートメントの下を使用して一方EFコアMySQLのパフォーマンス

var results = db.Posts 
    .Include(u => u.User) 
    .GroupBy(g => g.User) 
    .Select(g => new { Nick = g.Key.Name, Count = g.Count() }) 
    .OrderByDescending(e => e.Count) 
    .ToList(); 

を取ります完了するまで約16秒。

SELECT user.Name, count(*) c 
FROM post 
JOIN user ON post.UserId = user.Id 
GROUP BY user.Name 
ORDER BY c DESC 

私は何か間違っているか、MySqlのEFコアパフォーマンスがひどいですか?

+0

は、user.nameのインデックスに登録されていますか? –

+0

私はそうは思わない – Marduk

+0

実行される実際のSQLクエリのログを有効にしてみてください。私は実際に何が実行されているかは、あなたが書いた質問から遠いと思う。 EFが生成したクエリのそれぞれをmysql-cliで実行し、それらのクエリを実行します。あなたはボトルネックを見つけるでしょう – ironstone13

答えて

1

あなたの質問はさまざまなことを行っています。あなたのLINQツーエンティティクエリ内のいくつかの問題:

  1. あなたは熱心にdb.Posts内のすべての項目についてUserをロードしますInclude(...)を呼び出します。
  2. 各グループのレコードごとにCount()を呼び出します。これは、レコードをグループごとに1回だけカウントするように書き換えることができます。
  3. 最大の問題は、UserオブジェクトのNameプロパティのみを使用していることです。このフィールドだけを選択して同じ結果を見つけることができます。 150万の文字列を選択、グループ化、および返すことは、EFの高速処理である必要があります。

オリジナル:

var results = 
    db.Posts 
     .Include(u => u.User) 
     .GroupBy(g => g.User) 
     .Select(g => new { Nick = g.Key.Name, Count = g.Count() }) 
     .OrderByDescending(e => e.Count) 
     .ToList(); 

提案:EFコアはまだそれが可能に文をグループ化するのに制限があり

var results = 
    db.Posts 
     .Select(x => x.User.Name) 
     .GroupBy(x => x) 
     .Select(x => new { Name = x.Key, Count = x.Count() }) 
     .OrderByDescending(x => x.Count) 
     .ToList(); 

場合は、あなたが最初の後ToListを呼び出すことができますSelect(...)声明。

+0

あなたの例では、クエリ時間が144秒に短縮されましたが、2GBのメモリも必要でした。それでもmysql-cliよりもずっと悪いです。とにかくこれはいくつかの進歩です。 – Marduk

+1

私は毎日EFを使用していますが、EFよりも数分の1秒以上早く実行されるクエリを実行することはめったにありません。プロジェクトチームが許可している場合は、EFコアチームがエンタープライズプロダクションの準備が整うと発表するまで、完全なEFのためにEFコアを交換することをお勧めします。データベース側のグルーピングがない(この時点で)、EF Coreの魅力にもかかわらず、私のチームのプロジェクトがEF 6にロックされています。 –