How to improve performance of non-deterministic function of a column in a where clause or join?

左心房为你撑大大i 提交于 2019-12-04 03:32:59

问题


I would like to improve the performance of a query, which does has a where clause with a non-deterministic function call.

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

I think the question is equally valid for Joins:

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

Since

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

is non-deterministic I cannot create a view with a calculated column and index it. see: SQL Server (2005) - "Deleted On" DATETIME and Indexing

What options do I have to improve performance?


回答1:


Besides the non-deterministic function, the problem I see is that you do calculations on a field. This (usually) makes any index on the field unusable by the query.

The second paragraph of this link (Ten Common SQL Programming Mistakes (Functions on indexed columns in predicates)) provides more detailed info on when this happens, how to avoid it and how sometimes optimizers can use indexes despite the use of functions.

In short, instead of relying on improved optimizers, it's often possible to change the query by keeping the field intact (without doing any calculations on it), but instead doing the (reversed) calculations to the other values. In your case to the current date that is provided by GetDate(). Then the query can use the index of the field table1.Date.

So, you can use something like:

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

And you only need to find functions that get you the first and last day of current month.

This blog post can help you: sql-server-query-to-find-first-and-last-day-of-current-month/

Even better, this StackOverflow question/answer: simplest-way-to-create-a-date-that-is-the-first-day-of-the-month-given-another-date

I'll have to test but I think this slight variation of the above will do:

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) 



回答2:


Have you tried to use the Local Temporary Table to first insert all the required records ? Finally, do the calculations on temporary table and return it.



来源:https://stackoverflow.com/questions/6233319/how-to-improve-performance-of-non-deterministic-function-of-a-column-in-a-where

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!