【问题标题】:How to improve performance of non-deterministic function of a column in a where clause or join?如何提高 where 子句或连接中列的非确定性函数的性能?
【发布时间】:2011-06-03 22:35:52
【问题描述】:

我想提高查询的性能,它确实有一个带有非确定性函数调用的 where 子句。

Select Count(*) 
From table1
Where DateDiff(month, Cast(table1.Date As DateTime), GetDate()) = 0

我认为这个问题对 Joins 同样有效:

Select table1.column1
From table1 Inner Join table2 
On table1.MonthOfHappyness = 
DateDiff(month, Cast(table2.SomeDate As DateTime), GetDate()) 

自从

DateDiff(month, Cast(adrPkt.PktRevDato As DateTime), GetDate()) 

是非确定性的 我无法使用计算列创建视图并将其编入索引。 见:SQL Server (2005) - "Deleted On" DATETIME and Indexing

我有哪些选项可以提高性能?

【问题讨论】:

    标签: sql-server performance sql-server-2005 join where-clause


    【解决方案1】:

    除了非确定性函数之外,我看到的问题是您在字段上进行计算。这(通常)使查询无法使用该字段上的任何索引。

    此链接的第二段 (Ten Common SQL Programming Mistakes (Functions on indexed columns in predicates)) 提供了有关何时发生这种情况、如何​​避免这种情况以及优化器有时如何在使用函数的情况下使用索引的更详细信息。

    简而言之,通常可以通过保持字段完整(不对其进行任何计算)来更改查询,而不是依赖改进的优化器,而是对其他值进行(反向)计算。在您的情况下,到GetDate() 提供的当前日期。那么查询就可以使用table1.Date字段的索引了。

    所以,你可以使用类似的东西:

    SELECT COUNT(*) 
    FROM table1
    WHERE table1.Date
          BETWEEN
                 /* First Day of Current Month */
              AND 
                 /* Last Day of Current Month */
    

    而且您只需要找到可以为您提供当月第一天和最后一天的函数。

    这篇博文可以帮助你:sql-server-query-to-find-first-and-last-day-of-current-month/

    更好的是,这个 StackOverflow 问题/答案:simplest-way-to-create-a-date-that-is-the-first-day-of-the-month-given-another-date

    我必须进行测试,但我认为上面的这种轻微变化会做:

    SELECT COUNT(*) 
    FROM table1
    WHERE table1.Date 
          >=      /* First Day of Current Month */
            DATEADD(mm, DATEDIFF(mm, 0, GetDate() ), 0) 
      AND table1.Date 
          <       /* First Day of Next Month */
            DATEADD(mm, 1 + DATEDIFF(mm, 0, GetDate() ), 0) 
    

    【讨论】:

    • 谢谢!在我看来,以这种方式解决问题的原理(通过反转函数来隔离列(可以被索引))很好。您没有解决演员阵容问题,但是可以类似地解决。我的 where 子句的结尾类似于:Where table1.Date &lt; Convert(Varchar, DATEADD(mm, DATEDIFF(mm, 0, GetDate() ) , 0), 126) And table1.Date &gt;= Convert(Varchar, DATEADD(mm, DATEDIFF(mm, 0, GetDate() ) + 1, 0), 126 链接也不错。
    【解决方案2】:

    您是否尝试过使用Local Temporary Table 首先插入所有需要的记录?最后对临时表进行计算并返回。

    【讨论】:

      猜你喜欢
      • 2013-05-21
      • 1970-01-01
      • 2014-12-27
      • 1970-01-01
      • 1970-01-01
      • 2019-03-19
      • 1970-01-01
      • 2021-05-16
      相关资源
      最近更新 更多