解释不同LINQ语句之间的性能差异



我正试图解决以下问题:

我正在尝试优化这个查询:

(from ur in UserRates
where ur.BillingProperty == null
&& ur.JobPosition == null
&& ur.ValidFrom.Date <= date
&& (ur.ValidTo ?? DateTime.MaxValue).Date >= date
orderby ur.ValidFrom descending
select ur).FirstOrDefault();

不,这可能需要长达10秒的时间。

现在我试着玩LINQ方法链接,并用下面的语句将它降到了一秒钟:

UserRates.OrderByDescending(u => u.ValidFrom)
.FirstOrDefault(u =>
u.ValidFrom.Date <= date
&& (u.ValidTo ?? DateTime.MaxValue).Date >= date
&& u.BillingProperty == null
&& u.JobPosition == null);

然后我想知道,为什么这个SQL查询需要大约0秒才能执行:

SELECT *
FROM UserRate
Where ValidFrom <= @date
AND (ValidTo >= @date OR ValidTo IS NULL)
AND BillingPropertyID IS NULL
AND JobPositionId IS NULL
AND [UserId] = @UserId

@date和@userId填充的值与代码使用的值相同。

然后我切换到LINQ呼叫

UserRates.Where(u =>
u.ValidFrom.Date <= date
&& (u.ValidTo ?? DateTime.MaxValue).Date >= date
&& u.BillingProperty == null
&& u.JobPosition == null
).OrderByDescending(u => u.ValidFrom)
.FirstOrDefault();

再次执行大约需要5秒。我应该提到,我在UserRate表上创建了一个未聚集的索引

我只是没有看到差异在哪里,我感谢每一个朝着正确方向的暗示或推动。

您可以使用探查器在这两种情况下捕获准确的SQL语句,然后将它们的执行计划与服务器进行比较。这可能会让我们对这些差异有所了解。

我可以发现的一个潜在的性能瓶颈是,您正在比较DateTime列上的Date值。有时为了获得性能,你必须依赖于你的系统中的一个约定;ValidFrom";将始终存储为日期,或者只是避免SQL端转换。

例如,如果您希望确保ValidFrom在以下日期:

var validFrom = date.AddDays(1);
var latestUserRate = context.UserRates
.Where(ur => ur.BillingProperty == null 
&& ur.JobPosition == null
&& ur.ValidFrom < validFrom
&& (!ur.ValidTo.HasValue || ur.ValidTo >= date))
.OrderByDescending(ur => ur.ValidFrom)
.FirstOrDefault();

不进行.Date比较的要点是,服务器可以有效地利用表上的索引。越少的";调整";对表中的值进行处理,通常效果更好。

类似查询之间执行时间的差异可以归结为索引使用和执行计划选择。有时,这确实需要捕获有问题的SQL来仔细查看,然后调查建议的索引更改和可能的替代方案,以消除生成不良的语句。

相关内容

  • 没有找到相关文章

最新更新