Working with DATES in a SARGABLE way ...and gofast! ...All clearly explained!
Hi Guys,
Welcome to this new post!
We have already spoken many times about sargability.
For example here:
- Write high performing query: Is your query SARGABLE?
- SQL Server queries, write them Sargable: the ISNULL function
- https://sqlserverperformace.blogspot.com/2019/11/sargable-queries-part-2-examples.html
Sargability is the key factor to having a performant query but talking about dates is not always easy to get this property.
Today we will see how to turn a non sargable query using dates into a sargable one.
Enjoy!
Working with dates in a sargable way
For example when I use a function, but there are other cases..
Who has never used the datepart function?
Well, using this feature makes the query not-sargable!
For example, suppose you have a table called OrdTes that contains a datetime field DateOrd like the date of when an invoice was inserted.
Suppose you want to extract all invoices issued since last year..
We could write the following query:
We get the start of the current year by using the DATEPART function with the paramter yy (year)SELECT DATEORD FROM ORDTES WHERE DATEPART(yy,DATEORD) >=
DATEPART
(yy,GETDATE()) -1
Now to get the beginning of last year we subtract 1
Yes but how to write the part of the query at the right of the equal symbol using only the DATEDIFF and DATEADD function?SELECT DATEORD FROM ORDTES WHERE DATEORD >= ...
I do these 3 steps:SELECT DATEORD FROM ORDTES WHERE DATEORD) >=
DATEADD( yy,-1,DATEADD(yy,DATEDIFF(yy,0,GETDATE()), 0))
- First with the DATEDIFF(yy,0,GETDATE)) function returns the number of the years from the 1900 and so the value 122.
- Then with the DATEADD(yy, ... ) function i get the start of the current year and so the date 01/01/2022
- Finally i find the start of the last year with the DATEADD (yy, -1 ...) function called with the first parameter equal to yy (year) and the second parameter equal to -1 (i substract one year)
The Benchmark!
Now we can compare the two following query:Create table Ordtes (id integer identity(1,1), DateOrd datetime primary key (id)) Create index idx_Ordtes_DateOrd on Ordtes(Dateord) Declare @id integer = 0 While @id < 27656193
begin Insert into OrdTes (Dateord) Select dateadd(dd, -@id ,dateadd(yy,0,getdate())) set @id = @id + 1 end
Select DaTeOrd from OrdTes where DATEPART(yy,DateOrd) >= DATEPART(yy,GETDATE()) -1
Select DateOrd from OrdTes where DateOrd >= DATEADD( yy, -1, DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0))
By comparing the two esecution plans we found that the first query has the 100% of the weight...
We see also that the first query does the scan of the index while the second does a seek and so it is really sargable!
In addition, if the first query read all the 27656193 rows of the table in order to extract the single row needed...
...the sargable query read only 1 row, the row needed!
This to say that a sargable query is certainly more scalable and that a not sargable query is not scalable
And the results of the benchmark? witch query is the fastest?
These are the results!
Analyze results by yourself...
Conclusion
It is always worth writing sargable questions now even if we use dates!
We will have performance and scalability...
oh thank you!
ReplyDelete