0

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

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子句中函数的使用?

4

2 回答 2

5

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

WHERE DATEPART(WEEK, ArrivalDate) = 1

或者

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

例如,针对where 子句中的的函数,在大多数情况下会破坏可搜索性(换句话说,使索引查找无用并强制索引或表扫描)。

我知道有一个例外:

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

但我不会在任何其他情况下依赖它。

于 2013-04-04T14:50:57.807 回答
1

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

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

于 2013-04-04T14:50:01.410 回答