I am developing a .NET 5.0 API. I use EF to connect to a MySQL database and it works great. Though EF is very optimized I have one query that takes over a minute to complete :(
This endpoint combines user data from a lot of tables together in one query. To do this I use the Linq .Include(x => x.UserId). I have noticed that .Include() is very, very slow when you need to do it a lot of times like so:
var user = DatabaseContext.Users
.Include(user => user.Item1)
.ThenInclude(x => x.Item1)
.Include(user => user.Item2)
.Include(user => user.Item3)
.Include(user => user.Item4)
.Include(user => user.Item5)
.ThenInclude(x => x.Item1)
.SingleOrDefaultAsync(x => x.Id == userId)
);
In my case this leads to the query querying over 200.000 rows of data from the database because EF selects everything from a table and only in the end adds a WHERE clause to filter the data. Example below:
SELECT t.item,
t.item,
t.item,
u.item,
u.item,
..etc
FROM (SELECT a.item,
a.item
FROM table as a
LEFT JOIN table2 as c
ON a.foreignid = c.id
WHERE a.id == id
LIMIT 2) as t
LEFT JOIN table as u
ON t.id = u.id
LEFT JOIN (... another select)
ORDER BY t.id
I could use lazy loading which leads to significantly lower loading times but I have limited CPU power on the server so it would be problematic to run about 12 queries everytime I need this data. Especially if a lot of clients will use this endpoint at the same time (possibly hundreds at one time), so my preference is to do it in one database query.
So my question is: Is there any way to optimize the way EF handles the .Include() statement or is there another way to gain the expected result in a more efficient way?