我在Entity Framework中有一个查询,如下所示:
var dbModels = context.BusinessRuleExceptions
.Where(b => b.ResponseDateTime >= businessRuleSearchParameters.FromDate
&& b.ResponseDateTime <= businessRuleSearchParameters.ToDate
)
.GroupBy(x => new {x.BusinessRuleName, x.GenNextId})
.Select(p => p.OrderByDescending(pk => pk.ResponseDateTime).Take(1))
.SelectMany(e => e).ToList();
当我在SQL Server Profiler中捕获此查询时,它将转换为:
SELECT
[Limit1].[Id] AS [Id],
[Limit1].[OriginalCorrelationId] AS [OriginalCorrelationId],
[Limit1].[ServiceName] AS [ServiceName],
[Limit1].[BusinessRuleName] AS [BusinessRuleName],
[Limit1].[ResponseMessage] AS [ResponseMessage],
[Limit1].[ResponseDateTime] AS [ResponseDateTime],
[Limit1].[GenNextId] AS [GenNextId],
[Limit1].[SourceSystem] AS [SourceSystem]
FROM
(SELECT
[Distinct1].[BusinessRuleName] AS [BusinessRuleName],
[Distinct1].[GenNextId] AS [GenNextId]
FROM
(SELECT DISTINCT
[Extent1].[BusinessRuleName] AS [BusinessRuleName],
[Extent1].[GenNextId] AS [GenNextId]
FROM
[dbo].[BusinessRuleException] AS [Extent1]
WHERE
([Extent1].[ResponseDateTime] >= GetDate()-30)
AND ([Extent1].[ResponseDateTime] <= GetDate())
) AS [Distinct1] ) AS [Project2]
OUTER APPLY (SELECT TOP (1) [Project3].[Id] AS [Id],
[Project3].[OriginalCorrelationId] AS [OriginalCorrelationId],
[Project3].[ServiceName] AS [ServiceName],
[Project3].[BusinessRuleName] AS [BusinessRuleName],
[Project3].[ResponseMessage] AS [ResponseMessage],
[Project3].[ResponseDateTime] AS [ResponseDateTime],
[Project3].[GenNextId] AS [GenNextId],
[Project3].[SourceSystem] AS [SourceSystem]
FROM ( SELECT
[Extent2].[Id] AS [Id],
[Extent2].[OriginalCorrelationId] AS [OriginalCorrelationId],
[Extent2].[ServiceName] AS [ServiceName],
[Extent2].[BusinessRuleName] AS [BusinessRuleName],
[Extent2].[ResponseMessage] AS [ResponseMessage],
[Extent2].[ResponseDateTime] AS [ResponseDateTime],
[Extent2].[GenNextId] AS [GenNextId],
[Extent2].[SourceSystem] AS [SourceSystem]
FROM [dbo].[BusinessRuleException] AS [Extent2]
WHERE ([Extent2].[ResponseDateTime] >= GetDate()-30) AND ([Extent2].[ResponseDateTime] <= GetDate() )
AND ([Project2].[BusinessRuleName] = [Extent2].[BusinessRuleName])
AND (([Project2].[GenNextId] = [Extent2].[GenNextId])
OR (([Project2].[GenNextId] IS NULL) AND ([Extent2].[GenNextId] IS NULL)))
) AS [Project3]
ORDER BY [Project3].[ResponseDateTime] DESC ) AS [Limit1]
此转换后的查询非常慢,命令执行时间为数小时。我已经直接在SQL中编写了所需的查询,如下所示,这是一种执行迅速的查询:
WITH ranked_messages AS
(
SELECT
p.*,
ROW_NUMBER() OVER (PARTITION BY BusinessRuleName, GenNextId ORDER BY ResponseDateTime DESC) AS rn
FROM
BusinessRuleException AS p
WHERE
ResponseDateTime >= @FromDate
AND ResponseDateTime <= @ToDate
)
SELECT *
FROM ranked_messages
WHERE rn = 1
我不确定如何转换或优化EF LINQ查询以使其执行更快
答案 0 :(得分:0)
此命令的执行速度与给定的sql查询相同:
var dbModels =
from bre in context.BusinessRuleExceptions
where bre.ResponseDateTime >= businessRuleSearchParameters.FromDate
&& bre.ResponseDateTime <= businessRuleSearchParameters.ToDate
group bre by new { bre.BusinessRuleName, bre.GenNextId }
into g
let maxResponseDateTime = g.Max(x => x.ResponseDateTime)
let res = context.BusinessRuleExceptions.FirstOrDefault(p => p.ResponseDateTime == maxResponseDateTime &&
p.BusinessRuleName == g.Key.BusinessRuleName &&
p.GenNextId == g.Key.GenNextId)
select res;