Marduk
Marduk

Reputation: 389

EF Core Mysql performance

I have Mysql database with ~1 500 000 entities. When I try to execute below statement using EF Core 1.1 and Mysql.Data.EntityFrameworkCore 7.0.7-m61 it takes about 40minutes to finish:

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();

On the other hand using local mysql-cli and below statement, takes around 16 seconds to complete.

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

Am i doing something wrong, or EF Core performance of MySql is so terrible?

Upvotes: 0

Views: 1277

Answers (1)

Austin Drenski
Austin Drenski

Reputation: 506

Your queries are doing different things. Some issues in your LINQ-to-Entities query:

  1. You call Include(...) which will eagerly load the User for every item in db.Posts.
  2. You call Count() for each record in each group. This could be rewritten to count the records only once per group.
  3. The biggest issue is that you're only using the Name property of the User object. You could select just this field and find the same result. Selecting, grouping, and returning 1.5 million strings should be a fast operation in EF.

Original:

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();

Suggestion:

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();

If EF core still has restrictions on the types of grouping statements it allows, you could call ToList after the first Select(...) statement.

Upvotes: 1

Related Questions