SQL Serverデータベースに対してかなり複雑なSQLクエリが実行されるレポートを作成するように求められました。レポートのサイトはすでに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に切り替え、クエリは非常に迅速に実行されました。私はSQLプロファイラを使用してLINQを生成したSQLを見ましたが、いつものように荒々しく見えましたが、LINQ文を最適化してより効率的にする方法についての手がかりは見つかりませんでした。 EFおよびLINQを効率的に処理するために、または私はトリックを見逃しているため、このクエリでは、あまりにも複雑さ:
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
私は思ったんだけど次のとおりです。
ここでストレートTSQLのバージョンがありますか?
私はFirstOrDefaultsがそれを引き起こしていると推測しています。 groupbyの前に 'let response = r.First()'を追加しようとしましたか? SelectとOrderByを入れ替える?このようにhttp://stackoverflow.com/a/5013740/736079 – jessehouwing
'User.Responses'のようなナビゲーションプロパティはありますか? –
@ letess応答を使用するjessehouwingは、LINQのバージョンはまだADO.NETよりもはるかに遅いですが、かなり役立ちます。これを回答として入力すると、少なくともアップアップします。私はJon Skeetの選択と注文を入れ替える戦略に問題があります。主に、この構成でカウントを得る方法を見つけることができません。 –