YEAR 函数仍然不可SARGable 吗?

J. *_*ini 4 sql t-sql sql-server optimization date

在一本关于 SQL Server 2014 的书中,建议我避免

SELECT orderid, orderdate, filler
FROM dbo.Orders
WHERE YEAR(orderdate) = 2014;
Run Code Online (Sandbox Code Playgroud)

并且更喜欢

SELECT orderid, orderdate, filler
FROM dbo.Orders
WHERE orderdate >= '20140101'
AND orderdate < '20150101';
Run Code Online (Sandbox Code Playgroud)

当存在聚集索引时,orderdate因为使用YEAR会使查询不可SARGable。

自 SQL Server 2014 以来,这种情况有变化吗?如果是这样,它是在哪个版本中更改的?

Mar*_*ith 6

是的 - 它仍然不可控制(2022 Fiddle)。

Connect 站点上的几个相关请求(回程机器链接)是

但这些迄今为止从未实施过。YEAR对第二个(特别提到)的回应是

感谢您的反馈。我们会在未来的版本中考虑这一点,我同意这将是一个有价值的补充。不过,有很多解决方法,所以我不认为它是高优先级的。例如,使用日期维度表并将其连接到日期列上的大型表。在连接之前过滤日期维度上的日期。这样您就可以在连接期间进行索引查找以消除数据范围。

索引视图和列存储索引对于这种情况也可能有用。

您知道竞争对手是否可以执行您描述的这种特定查询转换吗?

对我来说,这似乎确实是可以在 SQL Server 2016“它只是运行得更快”标语下考虑的事情,但大概事实并非如此!

DATETRUNC函数也不可控制,但至少理解在应用于DATETRUNC列时将保留该列的顺序 - 因此可以避免在按年份分组时进行不必要的排序。

如果要实现这一点,我认为可以通过使用动态查找机制CAST以与to的可控制性类似的方式来完成。DATE

即使在这种情况下,直接将其表达为>= ... <范围仍然比仅仅依靠动态查找来对其进行排序更有效。