David Alcock

Monitoring SQL Server with Dynamic Management Objects – Sessions and connections

May 12, 2017 by

A fundamental task of Database Administrators is monitoring SQL Server performance. Whilst SQL Server does give us a user interface inside management studio that enables us to view current activity (in the rather aptly named Activity Monitor) this article is going to focus on querying Dynamic Management Objects with T-SQL to return various pieces of useful process information that we can use to monitor server usage.

To begin with we’ll perform a very simple select statement on a DMV that is used to return information on the current authenticated sessions within our instance.

Note that I have given the DMV an alias of ‘s’ which will help simplify our queries when we come to join to other objects.

This returns a lot of information in terms of both columns and rows so we’ll focus on reducing the result set returned to essentially ignore any rows that relate to internal system tasks.

We can achieve this by adding a very simple where clause to our query:

The first result set contained mainly NULL column values for the host, program and client columns which is indicative of system sessions. The second image on the other hand contains the actual values where we can see the originating machine of any active sessions (host_name) and what application is being used (program_name) as well as the unique session ID’s and login time of the session that were available for system tasks also.

At this point it is worth mentioning a common misconception about session ID’s. In my second result set we can see session IDs associated with user processes are taking up the numbers 51 to 54. The misconception is that any ID above 50 indicates a user process which actually isn’t quite the case and whilst you’ll never find user processes using an ID that is 50 or below system processes can and often will use session IDs over 50. This is why we use a where clause based on the is_user_process column being equal to 1 rather than use a session_id > 50 predicate.

Now that we’ve appropriately limited the result set we need to be a bit more selective on our columns rather than return every single one. At this point, if you haven’t already done so, it’s worth scrolling through the results to see what other information column we can start to use, for example, we can return information that focused on the sessions user details with the following query:

Whilst this does show who has sessions on our instance the information is still very limited. Let’s begin adding to our query by using the database ID column in the sessions view to our query; on its own it might not be very meaningful to us if it’s a system we’re not familiar with so we can utilise a function named DB_NAME that allows us to pass in the database ID and have the corresponding database name returned to us.

Here’s the database related columns returned on my test box:

We’ll now start looking at additional session information, including current status and values that relate to their associated workloads. We will still stay with the sys.dm_exec_sessions view and return some additional columns using the query below:

I’ve added two lines; one to return the current status of each session and another that returns read/write information.

The status column can be one of four values, running or sleeping as in the image above that tells us if the session is active or not running. It can also be dormant, meaning the session has been reset or it can have a status of preconnect which relates to the Resource Governor.

We can also view the related workload of each session by noting the read/write values. The read column indicates reads that have come from disk, which is substantially slower than reads from cache indicated by the logical_reads column.

The writes column indicates write operations (surprise!), it is worth pointing out that the values any of the reads and writes columns do not correspond to table rows but database pages. If we want row information we can add the row_count column from the sys.dm_exec_sessions DMV to return that particular piece of information:

In the image above I’ve highlighted the row containing the session information for the very same query that we are executing. Note the row_count of 4 which is the same result set that we are working with and also note that the row status is running meaning the session has effectively been captured mid-execution.

We could also modify our where clause to use a system function named @@SPID to only view information that relates to our specific query:

In the opposite way, we can use the function to exclude our query from the results as we would be focusing on other processes that are running on the instance:

At this point we will return information that is contained outside of the sys.dm_exec_sessions DMV and start to join another Management View to see what other information we can add to our query results, we’ll do so by first running this simple select statement:

As the name implies, this DMV returns information on the established physical connections to our SQL Server instance. We could use a query similar to the one below to look at a more limited result set.

This is the result set on my test instance, as I’m querying from the same machine we don’t see information like client IP or port details and being local the net_transport column is using Shared memory rather than TCPIP or Named Pipes. Unlike the sys.dm_exec_sessions DMV the connections view does not contain rows that correspond to internal system processes.

Of course at this point we have two completely separate queries, one for our session related information and another for physical connections. To bring them together we can perform an inner join using the session ID column which importantly exists in both views to merge our result sets:

Our query is now joining matching session IDs between the two DMV’s, just as we would tables (remember that a view is essentially a virtualised table) and we can now add columns from the connections DMV into our select query:

Returned information from both session and connection DMVs:

Please note there is a one to one relationship between connections and sessions and the corresponding management views.

This is now an ideal point to highlight the aliases that have been used in the query. In our query we are using the aliases s and c for the session and connection Management Views so let’s modify our select statement and remove the alias for session ID and all the other columns so we’re left with the following:

If we try to run the query we’ll get the following error:

Msg 209, Level 16, State 1, Line 1
Ambiguous column name ‘session_id’.

This is because the session_id column exists in both the session and connection DMVs so the engine is telling us that it simply doesn’t know which one to return, sessions or connection session_id.

In this case the alias allows us to very specify which DMV the column should come from. As we are joining on exact matches on the same column the value won’t be different whether we specify the session ID from the session or the connection DMV as demonstrated below (note the column alias I’ve used to differentiate between the two DMV columns).

The alias has proved to be useful for session ID because the values represent the very same thing in both the sessions and connections view and it’s certainly common to find columns in different DMVs that are duplicated, that’s really for ease of querying.

The final demonstration is to show two columns in our DMVs that although named differently could be confused to mean the same thing, when actually they are very different.

Remember in the sys.dm_exec_sessions DMV we looked at reads and writes of all the sessions on our instance? Well, the sys.dm_exec_connections DMV also has read and write columns (num_reads and num_writes) and we might be tempted to think that by querying both columns we’d get exactly the same results.

Again, using column aliases I can view writes from the sessions view (SessionWrites) and the corresponding writes from the connections view (ConnectionWrites) side by side, here’s the output:

They’re quite different and actually, it’s not that surprising why because when we look up the DMV information on Books Online the definition of the columns are very different:


writes bigint Number of writes performed, by requests in this session, during this session. Is not nullable.


num_writes int Number of data packet writes that have occurred over this connection. Is nullable.

The sessions view is based around page writes, but the connections view isn’t based on page level information at all but packets, which makes perfect sense as we’re looking at purely connection related information.

This highlights two things, the first is the depth of information that we can retrieve from DMVs but secondly, we need to ensure we understand both what information the DMV is based on and what the columns mean, like many things in SQL an assumption will often be incorrect.

So for our query, if we wanted to add both columns in our monitoring script and cover network information then there is nothing stopping us!

Whilst still relatively straight forward this query has introduced the functionality that Dynamic Management Views provide, especially for monitoring purposes. We’ve utilised some fundamental T-SQL concepts such as Joins, Functions and Aliases to bring back some incredibly useful information that we can use for checking activity on our instance.

The previous article in this series:

David Alcock

About David Alcock

David is a SQL Server professional based in the UK and is the Director and Principal Consultant of DTA I.T. Consultancy Ltd. He specialises in the design, administration, maintenance and optimisation of SQL Server solutions as well as delivering bespoke training courses to organizations. He has over 10 years experience working with SQL Server in different roles such as DBA, Database Developer and BI specialist. He has worked as Technical Lead on numerous mission critical projects in various sectors such as local government, finance, charities and retail. David is extremely passionate about SQL Server and keeps his own blog at http://sqlclarity.blogspot.com/ where he shares his views on the Data Platform. In his spare time he loves spending time with his family, watching movies and cooking Asian cuisine! View all posts by David Alcock