我正试图解决以下问题:
我正在尝试优化这个查询:
(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来仔细查看,然后调查建议的索引更改和可能的替代方案,以消除生成不良的语句。