SQLServerデータベースに対するかなり複雑なSQLクエリによって駆動されるレポートを作成するように依頼されました。レポートのサイトはすでにEntityFramework4.1を使用していたので、EFとLINQを使用してクエリを作成しようと思いました。
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に切り替えて、クエリを非常に迅速に実行しました。私はSQLプロファイラーを使用してLINQで生成されたSQLを調べましたが、いつものようにひどいように見えましたが、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が効率的に処理するには複雑すぎるのか、それともトリックを見逃したのかということです。