【发布时间】:2021-09-24 18:47:53
【问题描述】:
我正试图解决以下问题:
我正在尝试优化这个查询:
(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 表上创建了一个非聚集索引
我只是不知道差异在哪里,我感谢每一个提示或朝着正确方向的推动。
【问题讨论】:
-
ur.ValidFrom.Date <= date和ValidFrom <= @date在逻辑和性能方面都存在巨大差异。 (仅提及 LINQ 和 SQL 语句之间的一个显着区别)。 -
linq 语句不会被翻译成带有“where”部分的 sql select 语句,包含上述过滤器吗?老实说,我不明白你的意思。
-
空白不花钱,你知道的。如需更好的 SQL 性能帮助,请通过 https://brentozar.com/pastetheplan 分享相关查询计划。还请edit您的问题并添加表和索引定义。如果我不得不猜测,
u.ValidFrom.Date <= date和(u.ValidTo ?? DateTime.MaxValue).Date >= date可能没有帮助,而且很可能FirstOrDefault导致TOP 1生成,这可以让编译器认为它会很快得到结果并选择一个完全不同的计划。您在 SQL 中也没有ORDER BY,这会产生巨大的影响 -
ur.ValidFrom.Date从日期中截断时间部分,因此在比较之前会对其进行更改。但更糟糕的是,它不是sargable。那是什么,我最近解释了here。史蒂夫的回答也提到了这一点,尽管没有使用 sargable 这个词。 -
查看生成的 SQL 至少会向您揭示它与您编写的 SQL 非常不同。在尝试解释性能差异时,这始终是第一步。
标签: c# sql sql-server entity-framework linq