Wednesday, March 13, 2013

SQL SERVER – Avoid Using Function in WHERE Clause – Scan to Seek


-->
-->"Don't use functions in the WHERE clause, they reduce performance."
I hear this quite often. This is true but this subject is hard to understand in a single statement. Let us see what it means and how to use the function in the WHERE clause.
We will be using sample database AdventureWorks in this example. Additionally, turn on STATISTICS IO ON settings so we can see various statistics as well.
USE AdventureWorks2012
GO
SET STATISTICS IO ON
GO
Let us first execute following query and check the execution plan and statistics.
-- SCAN - Select values from SalesOrderDetail
SELECT [SalesOrderID], [SalesOrderDetailID], [ModifiedDate]
FROM [Sales].[SalesOrderDetail]
WHERE DATEDIFF(YEAR,ModifiedDate,GETDATE()) < 0
GO
Table 'SalesOrderDetail'. Scan count 1, logical reads 1246
You can see that the above query is scanning the whole table as well even though it is not returning any result it is reading 1246 pages from database.
In this case we are retrieving the data based on the ModifiedDate so we will create an index on the ModifiedDate Column.
-- Create Index on ModifiedDate
CREATE NONCLUSTERED INDEX [IX_SalesOrderDetail_ModifiedDate]
ON [Sales].[SalesOrderDetail] ([ModifiedDate])
GO
Now we have created an index on the ModifiedDate column we will once again execute the same query which we had run earlier.
-- SCAN - Select values from SalesOrderDetail
SELECT [SalesOrderID], [SalesOrderDetailID], [ModifiedDate]
FROM [Sales].[SalesOrderDetail]
WHERE DATEDIFF(YEAR,ModifiedDate,GETDATE()) < 0
GO
Table 'SalesOrderDetail'. Scan count 1, logical reads 338
You can see that the above query is still scanning the whole table as well even though it is not returning any result it is read over 338 pages from database.
The reason for the same is because in the query we are using the function DATEDIFF over the column ModifiedDate. As the outcome of this function is evaluated at the run time, the SQL Server Query engine has to scan the whole table to get necessary data.
To avoid this situation, let us try to avoid using the function on the column of the table and re-write the query. To re-write the query let us first understand what the query is retrieved. It is retrieving all the rows where the year difference between ModifiedDate and Current Date is less than 0. In other words what it means is that we need to retrieve the records which have a future date. We can simply re-write above query in the following way.
-- SEEK - Select values from SalesOrderDetail
SELECT [SalesOrderID], [SalesOrderDetailID], [ModifiedDate]
FROM [Sales].[SalesOrderDetail]
WHERE ModifiedDate > GETDATE()
GO
Table 'SalesOrderDetail'. Scan count 1, logical reads 3
Now let us execute the query and see the execution plan. We can see that there are only 3 logical read now and execution plan is also displaying Seek. This is because now we are not using any function over the column used in the WHERE clause.
To clean up you can run following script to drop the newly created index.
-- Cleanup
DROP INDEX [IX_SalesOrderDetail_ModifiedDate] ON [Sales].[SalesOrderDetail]
GO
In our case both the queries are returning the same result, a simple re-write can make a lot of difference.

If you are searching life partner. your searching end with kpmarriage.com. now kpmarriage.com offer free matrimonial website which offer free message, free chat, free view contact information. so register here : kpmarriage.com- Free matrimonial website