我正在寻找一些在数据库中进行性能调优的机会,并且我遇到了一个带有where where子句的select语句:
WHERE GETDATE() > DATEADD(mi,0,[TimeStamp])
我的问题是,以这种方式使用DATEADD是否有意义?我不明白为什么开发人员不会简单地使用它:
WHERE GETDATE() > [TimeStamp]
答案 0 :(得分:4)
[1] WHERE GETDATE() > [TimeStamp]
| WHERE Expression > Column
| WHERE Column < Expression
是SARG-able谓词,这意味着DBMS(例如SQL Server)可以使用Index Seek
(或Index Seek + Key|RID Lookup
)执行计划,以便快速查找并返回所需的行。< / p>
[2] WHERE GETDATE() > DATEADD(mi,0,[TimeStamp])
| WHERE Expression > ScalarFunction(Column)
| WHERE ScalarFunction(Column) < Expression
不是SARG-capable谓词,这意味着即使[Timestamp]
上有适当的索引,DBMS也无法使用Seek
。相反,将使用Table|Index|Clustered Scan
运算符,其(通常说但不总是 )性能低于Index Seek
(至少对于OLTP系统而言)。
因此DATEADD(mi,0,[TimeStamp])
强制在生成执行计划时使用Scan
数据访问运算符,即使存在正确的索引也是如此。没有DATEADD
DBMS可以使用Seek
运算符,不可以作为查询参数的某些/大多数值的最佳选择。*
我会测试两种解决方案(有和没有DATEADD(MINUTE, 0, ...)
),看看是否在性能方面存在差异。
注意#1:为了强制扫描,SQL2008R2引入了FORCESCAN
表提示(SQL2008也带有FORCESEEK
表提示)(references)。
注意#2:基本上,在[Timestamp]
列(DATEADD(mi,0,[TimeStamp])
)上应用的此函数在查询编译/查询优化期间也会产生影响,因为不能使用列统计信息。相反,因为操作不是=
,所使用的预定义选择性将是33%(据我记得,从视频演示来看 - 它不是官方/来自文档)。
答案 1 :(得分:0)
我认为编写此代码时开发人员犯了错误。
DATEADD
会降低性能,因为不会使用索引,作者也不会担心性能问题
https://www.sqlservercentral.com/Forums/608017/dateAdd-inside-where-clause
如果过滤值可以改变,那么写
会更好[TimeStamp] < DATEADD(MINUTE, 0, GETDATE())
在这种情况下,您不仅可以处理添加0分钟的情况,还可以处理其他情况(例如DATEADD(MINUTE, 10, GETDATE())
)