- Profiler
- Intro to Query Analyzer
Steps/Question |
Have you talked to users? I know this seems like common sense but talking to the users first can help point you in the next best direction |
Running ProfilerNow that you have an idea of query or queries the users were running , you can now set up the profiler to run.
Some events to capture Stored Procedure – RPC:Completed TSQL-SQL:Batchcompleted What to filter Duration > 5000 Milliseconds (5 sec) [More or less is up to you] Individual DBID to limit data to database in question. Application: Exclude ex. SQL Profiler,SQL Agent, MSQLEM (Emanager) Data columns to capture Duration: (group by) Event class: Tells you what event is being monitored DBID: Database (if needed) TextData: SQL statements that ran CPU Writes Read SPID ApplicationName NTUserName LoginName Benchmarking If you want to see how a typical work day would run on a new/test/development server, you can run a trace from production on those servers. This is a nice way to stress test a new server. Testing The query optimizer will REUSE a query if it is in the plan cache and this can play a role in how the execution plan is run. To view queries in Plan Cache: SELECT [cp].[refcounts] ,[cp].[usecounts] ,[cp].[objtype] ,[st].[dbid] ,[st].[objectid] ,[st].[text] ,[qp].[query_plan] FROM sys.dm_exec_cached_plans cp CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) st CROSS APPLY sys.dm_exec_query_plan(cp.plan_handle)qp When Testing a Query you should run the following: DBCC DROPCLEANBUFFER This forces all dirty pages for the current database to be written to disk and cleans the buffers. DBCC FREEPROCCACHE WITH NO_INFOMSGS Freeing the plan cache causes, for example, a stored procedure to be recompiled instead of reused from the cache. SET STATISTICS IO ON SET STATISTICS TIME ON Good info on logical reads and query time What to do with the data? Now that you have the data collected, you might see a lot of queries that ran based on your filter. This is where the grouping by Duration pays off. If the end users explained to you that slowness only occurred during a certain part of an application, you can search by ApplicationName,NTUserName or LoginName and see what SQL was run in the TextData column. You can also prioritize the output based on the longest running queries. Execution Plan Now that we have an idea of what query or queries that are slow, you need to move the query to query analyzer to view the execution plan. If the TextData from profiler showed a stored procedure, you will need to find and open the stored procedure in enterprise manager and copy to query analyzer. You will also need to add the parameters to the stored procedure that showed up in profiler. The execution plan is a great tool to answer the following.
Execution Plan Icons Each icon allows you to put the cursor over to view a Tool Tip box. The following is information that is displayed within this Tool Tip: TOOL TIP Cache Plan Size This shows how much memory the query will take up in the procedure cache. Gives you an idea of what plans are using in memory. Estimated Operator Cost Estimated plan generated by the optimizer. Estimated Subtree Cost Shows the accumulated optimizer cost. Read from right to left when reading steps. Represents the amount of time the optimizer thinks the operator will take. Estimated Number of Rows The number is created based on statistics on the table or index. Physical Operation This shows what actually happened. Logical Operation The results of the optimizer for what should happen if executed. Ordered Shows if the data that this operation is working on is in an ordered state. NodeID This shows the order numbered from left to right even though plan should be read right to left. ICONS Clustered Index Scan Optimizer decides that so many rows need to be returned that it’s quicker to scan all the records in the index rather than use keys provided by the index. Fine tune WHERE clause. Clustered Index Seek Optimizer tells the storage engine to look up data based on the keys of the index. Key values are used to quickly identify the row, or rows of data needed. Non Clustered Index Scan (INDEX SEEK) Uses index to look up the data/rows to be returned. The optimizer might be able to finds all the data in the non clustered index, or it might have to look up the data in the clustered index(if one) slightly hurting performance due to additional I/O needed to perform the extra look up. Key Lookup Always accompanied by the Nested Loop Join operation that combines the results of the two operations. It is a Bookmark Lookup on a table with a clustered index which points to either the RID of the non clustered index or the KeyID of the clustered index. Means that the optimizer cannot retrieve the rows in a single operation and has to use a clustered index. An indication the query could benefit from a COVERING or INCLUDED index. These include all of the columns that need to be returned by the query, all the columns of each row are found in the index, and a Key Lookup does not have to Occur in order to get all the columns that need to be returned. Nested Loop Because a Key Lookup is needed, the Nested Loop Join is needed to combine the rows of the Index Seek and Key Lookup. Table Scan Rows returned by scanning table. Usually occurs due to no useful indexes. Check index and/or WHERE clause. Clustered Index Scan Optimizer decides that so many rows need to be returned that it’s quicker to scan all the records in the index rather than use keys provided by the index. RID Lookup Query performs Index Seek on Primary Key. If Tool Tip shows Bmk… in Output List, this means that not all data was present in the index. This shows that the Index Seek is part of a query that has a Bookmark Lookup. The query performs a RID Lookup, which is a type of Bookmark Lookup that occurs on a HEAP table (No Index) and uses a RID to find the rows to return. Since table does not have a Clustered Index, it must use a RID that links the Index to the HEAP. This adds I/O because two different operations have to be performed instead of one operation, which are then combined with a Nested Loop operation. Add a Clustered Index, or use a Covering or Included index. DEALING WITH TABLE JOINS Index Scan The output of the INDEX SCANS is combined through a HASH MATCH. Hash Match (Join) Hashing is where data is converted into a symbolic form. HASHING TABLE is a data structure that divides all of the elements into equal sized groups to allow quick access to the elements. A HASH MATCH occurs when SQL joins two tables by HASHING the rows of the smaller table to be joined and then inserts the data into a HASH Table, then processing the larger table one row at a time against the smaller table looking for matches where rows need to be joined. The Hashed Table minimizes the size of the smaller table, this makes table comparisons to be quick. Clustered Index Seek Usually see this after a Hash Match Join. Nested Loop Join Following a Clustered Index Seek, the data accumulated by the other operations are joined with the data collected from the Seek though a Nested Loop. The Nested Loop Join operation takes the input from two sets of data and joins them by scanning the outer data set (the bottom operator in a graphical execution plan) once for each row in the inner set. The number of rows in each of the two data sets was small, making this a very efficient operation. As long as the inner data set is small and the outer data set, small or not, is indexed, this becomes an extremely efficient join mechanism. Unless you have very large data sets, this is the type of join that you most want to see in an execution plan. Compute Scalar Usually see this after a Hash Match Join. |
Conclusion
Keep in mind that this in just and brief overview, However it should be a great place to start. I will attempt to add to this check list in the near future. (see below)
Things to remember:
- Appropriate Indexes
- Index Fragmentation
- Up-to-date Statistics
- Database Design
- Physical Hardware
- Server Performance
- Network