How to find your worst performing SQL Server queries

I get asked this question over and over again: “I have a SQL Server that is performing badly. How can I find the worst performing queries?”. So in today’s blog posting I want to give you some information and guidance that will let you answer this question very easily.

Ask SQL Server!

The nice thing about SQL Server is that SQL Server itself can answer almost all of your questions, because SQL Server stores a lot of troubleshooting information in various Dynamic Management Views (DMVs) and Dynamic Management Functions (DMFs). On the other hand this is also a bad thing, because you have to know the various DMVs/DMFs, and how to interpret and correlate them together.

One of the most important DMVs regarding your worst performing SQL Server queries is sys.dm_exec_query_stats. For every cached execution plan SQL Server stores detailed information about how this execution plan performed at runtime. And in addition SQL Server tells you how much CPU time and how much I/O this specific query consumed. This is one of the DMVs that I use on regular basis when I have to troubleshoot badly performing SQL Server installations.

Let’s get into sys.dm_exec_query_stats!

When you do a simple SELECT against sys.dm_exec_query_stats you get back a very wide result set with a lot of different columns – and with a huge amount of different numbers.

Who on earth can understand all these different numbers???

Let’s have a more detailed look at them. For every cached execution plan SQL Server gives you information about the following metrics:

  • Worker Time (columns …_worker_time)
  • Physical Reads (columns …_physical_reads)
  • Logical Writes (columns …_logical_writes)
  • Logical Reads (columns …_logical_reads)
  • SQLCLR Time (columns …_clr_time)
  • Elapsed Time (columns …_elapsed_time)
  • Row Count (columns …_rows)

And for every metric you get 4 different columns with aggregation information:

  • Total value
  • Last value
  • Min value
  • Max value

With this information to hand it is very easy to find out what your worst performing queries are. But first you have to know what your performance bottleneck is – is it CPU or I/O bound? If your performance bottleneck is CPU bound, you can ask SQL Server for your top 5 worst performing queries regarding CPU consumption with the following query:

-- Worst performing CPU bound queries
SELECT TOP 5
	st.text,
	qp.query_plan,
	qs.*
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.plan_handle) st
CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp
ORDER BY total_worker_time DESC
GO

As you can see I just do here a simple ORDER BY total_worker_time DESC to get back the CPU intensive queries. In addition I also grab the SQL statement and the execution plan itself by calling the DMFs sys.dm_exec_sql_text and sys.dm_exec_query_plan. The following query shows how to find your worst performing queries regarding I/O consumption.

-- Worst performing I/O bound queries
SELECT TOP 5
	st.text,
	qp.query_plan,
	qs.*
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.plan_handle) st
CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp
ORDER BY total_logical_reads DESC
GO

When you have the SQL statement and the execution plan in front of you, you can further troubleshoot the query and find out what caused the high CPU or I/O consumption.

Summary

SQL Server is an amazing product: it can immediately give you very good answers to your questions. You only have to know where to search for your answer. Regarding poor performing queries you should always start by analyzing the DMV sys.dm_exec_query_stats, where SQL Server stores runtime statistics about your execution plans.

Like or share to get the source code.

Thanks for your time,

-Klaus

Leave a Comment

Your email address will not be published. Required fields are marked *