TSQL:调整动态查询搜索

时间:2013-04-04 14:44:48

标签: sql-server tsql

在阅读调优TSQL查询时,我看到了关于避免(或小心)WHERE子句中的函数的建议。但是,在某些情况下 - 比如从今天开始需要动态日期的搜索 - 我很好奇是否可以进一步调整查询?例如,下面的查询使用DATEADD函数作为当前日期,这允许用户随时获取过去30天的正确信息:

SELECT *
FROM Zoo..Transportation
WHERE ArrivalDate BETWEEN DATEADD(DD,-30,GETDATE()) AND GETDATE()

如果我试图消除函数DATEADD,我可以声明一个变量,该变量将拉动该时间,然后使用存储在变量中的设置值查询数据,例如:

DECLARE @begin DATE
SET @begin = DATEADD(DD,-30,GETDATE())

SELECT *
FROM Zoo..Transportation
WHERE ArrivalDate BETWEEN @begin AND GETDATE()

但是,执行计划和统计显示完全相同的读取,扫描和批量成本。

在动态数据的这些实例中(例如,使用今天的日期作为起点),我们如何减少或消除WHERE子句中函数的使用?

2 个答案:

答案 0 :(得分:5)

where子句中的函数意味着做一些愚蠢的事情:

WHERE DATEPART(WEEK, ArrivalDate) = 1

或者

WHERE CONVERT(CHAR(10), ArrivalDate, 101) = '01/01/2012'

E.g。在where子句中对 columns 的函数,在大多数情况下会破坏sargability(换句话说,渲染索引无用并强制执行索引或表扫描)。

我知道有一个例外:

WHERE CONVERT(DATE, ArrivalDate) = CONVERT(DATE, GETDATE())

但我不会依赖于任何其他情况。

答案 1 :(得分:1)

IME,使用WHERE子句中的函数只是在对查询中的数据进行操作时才会出现问题 - 这意味着函数(本身可能是复杂的SQL)会针对查询中的每个值运行 - 这可能会导致表扫描或类似于optmiser不知道使用哪个索引(如果有)。

上面的示例使用DATEADD和当前日期 - 该值可能计算一次(或者如果为结果集中的每一行计算它,它将不会影响查询计划,因为它不包含来自你的查询)。