Мне было предложено подготовить отчет, в котором содержится довольно сложный SQL-запрос к базе данных SQL Server. Поскольку сайт отчета уже использовал Entity Framework 4.1, я думал, что я попытался бы написать запрос с помощью EF и LINQ:Есть ли способ оптимизировать этот запрос LINQ to Entities?
var q = from r in ctx.Responses
.Where(x => ctx.Responses.Where(u => u.UserId == x.UserId).Count() >= VALID_RESPONSES)
.GroupBy(x => new { x.User.AwardCity, x.Category.Label, x.ResponseText })
orderby r.FirstOrDefault().User.AwardCity, r.FirstOrDefault().Category.Label, r.Count() descending
select new
{
City = r.FirstOrDefault().User.AwardCity,
Category = r.FirstOrDefault().Category.Label,
Response = r.FirstOrDefault().ResponseText,
Votes = r.Count()
};
Этот запрос подсчитывает голоса, но только от пользователей, которые представили определенное количество требуемые минимальные голоса.
Этот подход был полной катастрофой с точки зрения производительности, поэтому мы переключились на ADO.NET, и запрос запустился очень быстро. Я просмотрел LINQ сгенерированный SQL, используя SQL Profiler, и хотя он выглядел ужасно, как обычно, я не видел никаких подсказок относительно того, как оптимизировать оператор LINQ, чтобы сделать его более эффективным.
Вот прямая версия TSQL:
WITH ValidUsers(UserId)
AS
(
SELECT UserId
FROM Responses
GROUP BY UserId
HAVING COUNT(*) >= 103
)
SELECT d.AwardCity
, c.Label
, r.ResponseText
, COUNT(*) AS Votes
FROM ValidUsers u
JOIN Responses r ON r.UserId = u.UserId
JOIN Categories c ON r.CategoryId = c.CategoryId
JOIN Demographics d ON r.UserId = d.Id
GROUP BY d.AwardCity, c.Label, r.ResponseText
ORDER BY d.AwardCity, s.SectionName, COUNT(*) DESC
Что мне интересно: является ли это запрос слишком сложный для EF и LINQ для обработки эффективно или я пропустил трюк?
Я предполагаю, что все FirstOrDefaults вызывают это. Вы пытались добавить 'let response = r.First()' перед группой? Или поменять Select и OrderBy? Как это http://stackoverflow.com/a/5013740/736079 – jessehouwing
Есть ли свойство навигации, например 'User.Responses'? –
@jessehouwing с использованием let response помогает значительно, хотя версия LINQ все еще намного медленнее, чем ADO.NET. Если вы введете это в качестве ответа, я, по крайней мере, выберу его. У меня возникли проблемы с стратегией поменять и упорядочивать Jon Skeet, в основном я не могу понять, как получить счет с помощью этой конструкции. –