开发者

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

I would like to improve the performance of a query, which does has a where clause wi开发者_Python百科th 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?


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) 


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜