我正在寻找一些在我的数据库中进行性能调优的机会,并且我遇到了一个带有此where子句的select语句:
WHERE GETDATE() > DATEADD(mi,0,[TimeStamp])
Run Code Online (Sandbox Code Playgroud)
我的问题是,以这种方式使用DATEADD是否有意义?我不明白为什么开发人员不会简单地使用它:
WHERE GETDATE() > [TimeStamp]
Run Code Online (Sandbox Code Playgroud)
[1] WHERE GETDATE() > [TimeStamp]| WHERE Expression > Column| WHERE Column < Expression是 SARG 可谓词,这意味着 DBMS(例如 SQL Server)可以使用Index Seek(或Index Seek + Key|RID Lookup) 作为执行计划,以便快速查找并返回所需的行。
[2] WHERE GETDATE() > DATEADD(mi,0,[TimeStamp])| WHERE Expression > ScalarFunction(Column)| WHERE ScalarFunction(Column) < Expression不是 SARG 谓词,这意味着即使[Timestamp]DBMS 上有适当的索引也无法使用Seek. 相反,Table|Index|Clustered Scan将使用(通常但并非总是)性能低于Index Seek(至少对于 OLTP 系统)的运算符。
因此,即使存在正确的索引,也会在生成执行计划时强制使用数据访问运算符DATEADD(mi,0,[TimeStamp])。Scan如果没有DATEADDDBMS,则可能使用的Seek运算符对于查询参数的某些/大多数值来说不是最佳选择。*
我会测试这两种解决方案(有和没有DATEADD(MINUTE, 0, ...)),看看性能方面是否有任何差异。
注意#1:为了强制扫描,SQL2008R2引入了FORCESCAN表提示(SQL2008也带有FORCESEEK表提示)(参考资料)。
注意#2:基本上,应用于[Timestamp]列 ( DATEADD(mi,0,[TimeStamp])) 的此函数也会在查询编译/查询优化期间产生影响,因为无法使用列统计信息。相反,因为操作不是=预定义的,所以使用的选择性将为 33%(据我从视频演示中记得 - 这不是官方/来自文档)。