【问题标题】:Is SQL DATEDIFF(year, ..., ...) an Expensive Computation?SQL DATEDIFF(year, ..., ...) 是一种昂贵的计算吗?
【发布时间】:2010-03-30 17:41:59
【问题描述】:

我正在尝试优化一些极其复杂的 SQL 查询,因为它需要很长时间才能完成。

在我的查询中,我使用许多相同的函数动态创建了 SQL 语句,因此我创建了一个临时表,其中每个函数只被调用一次而不是多次调用 - 这将我的执行时间缩短了 3/4。

所以我的问题是,如果说 1,000 次 datediff 计算缩小到 100 次,我能期望看到很大的不同吗?

编辑: 查询如下所示:

SELECT DISTINCT M.MID, M.RE FROM #TEMP INNER JOIN M ON #TEMP.MID=M.MID 
WHERE ( #TEMP.Property1=1 ) AND 
DATEDIFF( year, M.DOB, @date2 ) >= 15  AND  DATEDIFF( year, M.DOB, @date2 ) <= 17 

这些是作为字符串动态生成的(以零碎的形式组合在一起),然后执行,以便可以在每次迭代中更改各种参数 - 主要是最后几行,包含各种 DATEDIFF 查询。

大约有 420 个这样的查询,这些日期差异是这样计算的。我知道我可以轻松地将它们全部拉入临时表(1,000 个日期差异变为 50 个)-但这值得吗,它会在几秒钟内产生任何影响吗?我希望能在十分之一秒内得到更好的改进。

【问题讨论】:

  • 发布查询 - 当您在 2+ 个深度子查询中执行 DATEDIFF 时,并不能真正帮助您确认您的假设...

标签: sql query-optimization datediff


【解决方案1】:

对于性能影响的程度,诚实地说,这完全取决于您正在做什么。

例如,如果您在 WHERE 子句中使用 DATEDIFF(或实际上任何其他函数),那么这将导致性能下降,因为它会阻止在该列上使用索引。

例如基本示例,查找 2009 年的所有记录

WHERE DATEDIFF(yyyy, DateColumn, '2009-01-01') = 0

不会很好地利用 DateColumn 上的索引。而提供最佳索引使用的更好解决方案是:

WHERE DateColumn >= '2009-01-01' AND DateColumn < '2010-01-01'

如果您有兴趣,我 recently blogged 关于这带来的不同(通过性能统计/执行计划比较)。

这比将 DATEDIFF 作为结果集中的列返回要昂贵。

我将首先确定花费最多时间的单个查询。检查执行计划以查看问题所在并从那里进行调整。

编辑: 根据您给出的示例查询,您可以尝试以下方法来删除 WHERE 子句中对 DATEDIFF 的使用。查找在给定日期年满 10 岁的每个人的基本示例 - 我认为数学是正确的,但无论如何你都明白了!给它一个快速测试,看起来不错。应该很容易适应您的场景。如果您想在给定日期找到(例如)15 到 17 岁之间的人,那么这种方法也可以实现。

-- Assuming @Date2 is set to the date at which you want to calculate someone's age 
DECLARE @AgeAtDate INTEGER
SET @AgeAtDate = 10  

DECLARE @BornFrom DATETIME
DECLARE @BornUntil DATETIME
SELECT @BornFrom = DATEADD(yyyy, -(@AgeAtDate + 1), @Date2)
SELECT @BornUntil = DATEADD(yyyy, -@AgeAtDate , @Date2)

SELECT DOB
FROM YourTable
WHERE DOB > @BornFrom AND DOB <= @BornUntil

需要补充的一个重要说明是,对于从 DOB 计算的年龄,这种方法更准确。您当前的实施只考虑了出生年份,而不是实际日期(例如,2009 年 12 月 1 日出生的人在 2010 年 1 月 1 日将显示为 1 岁,而他们在 2010 年 12 月 1 日之前不是 1 岁)。

希望这会有所帮助。

【讨论】:

  • 正确,当然这适用于用于包装索引列的几乎任何函数,而不仅仅是DATEDIFF
  • @Aaronaught - 是的,谢谢你的收获。我已经更新了我的答案以使其更清楚
【解决方案2】:

与其他处理日期时间值的方法(如字符串)相比,DATEDIFF 非常有效。 (see this SO answer)。

在这种情况下,听起来您一遍又一遍地检查相同的数据,这可能比使用临时表更昂贵。例如,将生成统计信息。

【讨论】:

    【解决方案3】:

    您可以做的一件事来提高性能可能是在 MID 上的临时表上放置一个索引。

    检查您的执行计划是否有帮助(可能取决于临时表中的行数)。

    【讨论】:

      猜你喜欢
      • 2010-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-12
      相关资源
      最近更新 更多