When you run a query, SQL Server does two things...
- First it checks the validity of the query to ensure there are no syntactical errors and the objects that you are trying to use such as a table, view or a UDF actually exists.
- Once the first condition is satisfied, SQL Server then determines the fastest and shortest path it can take to execute your query. You may have indexes on the table(s), but whether SQL server will use them to execute your query largely depends on the optimizer. If a complete table scan is faster, then it will scan the table instead of indexes, but more often than not, it will use the indexes to determine the fastest route.
In order to see the query execution plan, open the Query Analyzer and navigate to Query > Display Estimated Execution Plan to see the execution plan without actually executing your query. If you want to execute query and also have query anlayzer display the execution plan select "Include Actual Execution Plan."
If you are running SQL Service Profile, you can capture an event called MISC:Execution Plan to show the execution plan used by the queries that are running in your environment.
You can also run "SET SHOWPLAN_TEXT ON" command in Query Analyzer to show execution plan for any subsequent queries that you may run. If your query uses temp tables, you will have run the command "SET STATISTICS PROFILE ON" before you run the query.
Below are some of the execution plans based off of some sample queries I ran.
1. Simple Select
SELECT U.UserName,S.StoreID FROM SecUsers U INNER JOIN SecUserStores S ON U.UserID=S.UserID
In this case, 39% of the cost is in join, 40% and 21% in index scan on two tables.
2. Union - note I am basically running same query twice, but you get the picture.
SELECT S.UserName,SS.StoreID FROM SecUsers S INNER JOIN SecUserStores SS ON S.SecUserID=SS.SecUserID
UNION ALL
SELECT S.UserName,SS.StoreID FROM SecUsers S INNER JOIN SecUserStores SS ON S.SecUserID=SS.SecUserID
In this case, since I am basically running same query twice, everything is doubled, but as you can imagine, more complex a query, more taxing.
3. Using Temp Table
DECLARE @tmpTable TABLE(UserName varchar(50), StoreID INT)
INSERT INTO @tmpTable(UserName,StoreID)
SELECT S.UserName,SS.StoreID FROM SecUsers S INNER JOIN SecUserStores SS ON S.SecUserID=SS.SecUserID
SELECT * FROM @tmpTable
You should avoid temp tables as much as possible, because SQL Server caches the optimal execution plan for regular stored procedures, but it can't do so for a temporary table and must determine the best execution plan everytime.
4. Sorting Example
SELECT S.UserName,SS.StoreID FROM SecUsers S INNER JOIN SecUserStores SS ON S.SecUserID=SS.SecUserID ORDER BY SS.StoreID
As you can see, Sort is costly. Try to avoid ORDER BY clause as much as you can. If you must sort, either create an index or sort in your code.
5. WHERE Clause
SELECT * FROM Orders WHERE BusDT > 30450
Sometime when you don't have appropriate indexes in place and you show an execution plan, optimizer will provide you an index that you can add to your table.
6. Using a UDF in WHERE Clause
SELECT * FROM Orders WHERE BusDT < dbo.Func_TOOADATE('01/01/2012')
Using a user defined function in where clause in taxing. In essence you are executing two queries. Also, as with temp tables, execution plan for in-line functions is not cached and optimizer must determine the execution plan everytime. You should avoid using functions in WHERE clause whenever possible.
No comments:
Post a Comment
As always, your comments are welcome and appreciated!