How to find CPU intensive queries

High CPU usage is a very common problem in SQL Servers. Any query with a bad query plan can steal CPU time and harm system response time.

Fortunately we can find queries with high CPU time using sys.dm_exec_query_stats DMV. This DMV, created in SQL Server 2008, keeps performance statistics for cached query plans, allowing us to find the queries and query plans that are most harming our system.

This DMV keeps some useful statistic information about the queries. All the values are stored in fields called “Total” and “Last”, this means we have the total value for all executions of the query and the value of the last execution of the query. For example, we have total_worker_time and last_worker_time.

Total_worker_time field can be used to find the most harmful query in the system, but this doesn’t mean this is the most CPU intensive query, this means this query is executed too many times. To find the most CPU intensive query we can use last_worker_time, but this query would not be a problem if it was executed only one or two times.

We can retrieve the query statement using a cross apply with sys.dm_exec_sql_text DMF, but this DMF will return the text for the entire batch, while each row in sys.dm_exec_query_stats keeps information about only one query. To solve this difference we have the fields statement_start_offset and statement_end_offset that points the exact position of the query inside the batch. We will need to do some string manipulation to retrieve the query text.

For last, but not least, we need to retrieve the query plan, so we can analyze the query plan and find the reason of the high CPU consumption. To do so, we need to do a cross apply with the sys.dm_exec_query_plan DMF.

To test this query, you can execute the following batch in a test environment to produce one query with high cpu usage:

Now, let’s check the most cpu intensive queries in our system: