【问题标题】:Is this date comparison condition SARG-able in SQL?这个日期比较条件是否可以在 SQL 中实现?
【发布时间】:2012-06-06 21:37:35
【问题描述】:

这种情况是否可以预测?

AND  DATEDIFF(month,p.PlayerStatusLastTransitionDate,@now) BETWEEN 1 AND 7)

我的经验法则是左侧的函数使条件不可分割。但在某些地方我读到 BETWEEN 子句是可分割的。 那么有人确定吗?

供参考:

注意:如果有任何大师到此结束,请更新 Sargable Wikipedia 页面。我对它进行了一些更新,但我相信它可以得到更多改进:)

【问题讨论】:

标签: sql sql-server database-performance


【解决方案1】:

使用 AdventureWorks,如果我们查看这两个等效查询:

SELECT OrderDate FROM Sales.SalesOrderHeader
WHERE DATEDIFF(month,OrderDate,GETDATE()) BETWEEN 1 AND 7;

SELECT OrderDate FROM Sales.SalesOrderHeader
WHERE OrderDate >= DATEADD(MONTH, -7, GETDATE())
  AND OrderDate <= DATEADD(MONTH, -1, GETDATE());

在这两种情况下,我们都会看到聚集索引扫描:

但请注意仅在后一个查询中推荐/缺失的索引,因为它是唯一可以从中受益的:

如果我们向 OrderDate 列添加索引,则再次运行查询:

CREATE INDEX dt ON Sales.SalesOrderHeader(OrderDate);
GO

SELECT OrderDate FROM Sales.SalesOrderHeader
WHERE DATEDIFF(month,OrderDate,GETDATE()) BETWEEN 1 AND 7;

SELECT OrderDate FROM Sales.SalesOrderHeader
WHERE OrderDate >= DATEADD(MONTH, -7, GETDATE())
  AND OrderDate <= DATEADD(MONTH, -1, GETDATE());

我们看到了很大的不同——后者使用了一个 seek:

还要注意您的查询版本的估计值是如何偏离的。这在大型数据集上绝对是灾难性的。

在极少数情况下,应用于列的函数或其他表达式是可搜索的。我知道的一种情况是CONVERT(DATE, datetime_column) - 但该特定优化没有记录在案,我建议无论如何不要使用它。不仅因为您暗示对列使用函数/表达式是可以的(并非在所有其他情况下都如此),还因为it can lead to wasted reads and disastrous estimates

【讨论】:

    【解决方案2】:

    如果这是可悲的,我会感到非常惊讶。一种选择可能是将其重写为:

    WHERE p.PlayerStatusLastTransitionDate >= DATEADD(month,1,CAST(@now AS DATE))
    AND   p.PlayerStatusLastTransitionDate <= DATEADD(month,7,CAST(@now AS DATE))
    

    我相信这会很受欢迎(尽管它不是那么漂亮)。

    【讨论】:

    • +1 :OPs 查询不是 SARGable。 table.field BETWEEN f(x) AND f(y) (或像 Abe 一样使用 &gt;=&lt;= 是 SARGable。几乎,如果你把搜索字段放在一个函数中,它就不会是 SARGable。相反,处理搜索的参数,如 Abe 的回答 :)
    • 这个答案可以改写为BETWEEN。重要的是,日期函数被应用于执行查询的常量表达式,而不是像 OP 查询那样应用于每一行。
    • 我建议不要在您自己的代码或您提供给他人的代码中使用 BETWEEN 进行日期时间查询。原因如下:sqlblog.com/blogs/aaron_bertrand/archive/2011/10/19/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-17
    • 2023-03-29
    • 1970-01-01
    • 2015-12-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多