Now you will take a look at which logins have the most open database connections, using the query shown in Listing 22.
LISTING 22: Login count information
-- Get logins that are connected and how many sessions they have
SELECT login_name, COUNT(session_id) AS [session_count]
FROM sys.dm_exec_sessions WITH (NOLOCK)
GROUP BY login_name
ORDER BY COUNT(session_id) DESC OPTION (RECOMPILE);
-- This can help characterize your workload and
-- determine whether you are seeing a normal level of activity
This query is one way to gauge whether you are
seeing a normal level of activity on your database server. You can look
at the number of connections for each login (especially if you use
application-level logins) to determine whether you are seeing a normal
workload. For example, if one of your logins typically sees about 150
active connections but you are seeing 350 connections for that login,
then you probably have good reason to suspect that your workload has
changed and your database server may be working harder than usual.
This query is also good for troubleshooting and
confirming database connectivity. If you are seeing active connections
for particular logins, then you know that at least some web or
application servers are able to connect using that login. You can also
use the old DBA trick of using a Microsoft Data Link (.udl file) to verify connectivity from a remote server.
You can easily create a Microsoft Data Link file
on any machine running Windows 2000 or newer by creating a new, empty
text file and then changing the file extension from .txt to .udl. Then
you can double-click on the .udl file and you will open a Data Link
Properties dialog. After you enter valid login credentials for the
database server and database that you want to connect to, you can click
on the Test Connection button to verify that you can make a database
connection to that database on that server. This is a good
troubleshooting tool that you can use on a web server or application
server that does not require any development tools to be installed to
verify connectivity from that server to the database server.
Next, using the query shown in Listing 23, you will take a look at some current task and pending I/O count information.
LISTING 23: Average Task Count information
-- Get Average Task Counts (run multiple times)
SELECT AVG(current_tasks_count) AS [Avg Task Count],
AVG(runnable_tasks_count) AS [Avg Runnable Task Count],
AVG(pending_disk_io_count) AS [Avg Pending DiskIO Count]
FROM sys.dm_os_schedulers WITH (NOLOCK)
WHERE scheduler_id < 255 OPTION (RECOMPILE);
-- Sustained values above 10 suggest further investigation in that area
-- High Avg Task Counts are often caused by blocking or other resource contention
-- High Avg Runnable Task Counts are a good sign of CPU pressure
-- High Avg Pending DiskIO Counts are a sign of disk pressure
This is one query that you will want to run
multiple times in quick succession, as the values returned change very
frequently, depending on your workload and how your SQL Server instance
is running. Any value for these three columns that stays above 10 for a
sustained period is cause for some concern. The Average Task Count (per
CPU scheduler) is a good indicator of your overall workload level.
Sustained high Average Task Counts are often caused by blocking or
other resource contention. The Average Runnable Task Count indicates
how many tasks are waiting for CPU time on each CPU scheduler. It is a
very reliable indicator of CPU pressure. The Average Pending DiskIO
Count measures how many pending I/O operations are on each CPU
scheduler, so it is a good indicator of overall I/O pressure. This
value in particular will jump around a lot as your I/O subsystem is
under stress. For all three of these columns, lower values are better
than higher values.
The next query, shown in Listing 24, will return your CPU utilization history over the last 256 minutes, in one-minute intervals.
LISTING 24: CPU utilization history
-- Get CPU Utilization History for last 256 minutes (in one minute intervals)
-- This version works with SQL Server 2008 and above
DECLARE @ts_now bigint = (SELECT cpu_ticks/(cpu_ticks/ms_ticks)
FROM sys.dm_os_sys_info WITH (NOLOCK));
SELECT TOP(256) SQLProcessUtilization AS [SQL Server Process CPU Utilization],
SystemIdle AS [System Idle Process],
100 - SystemIdle - SQLProcessUtilization
AS [Other Process CPU Utilization],
DATEADD(ms, -1 * (@ts_now - [timestamp]),
GETDATE()) AS [Event Time]
FROM (SELECT record.value(’(./Record/@id)[1]’, ‘int’) AS record_id,
record.value(’(./Record/SchedulerMonitorEvent/SystemHealth/SystemIdle)[1]’, ‘int’)
AS[SystemIdle],record.value(’(./Record/SchedulerMonitorEvent/SystemHealth/
ProcessUtilization)[1]’,’int’)
AS [SQLProcessUtilization], [timestamp]
FROM (SELECT [timestamp], CONVERT(xml, record) AS [record]
FROM sys.dm_os_ring_buffers WITH (NOLOCK)
WHERE ring_buffer_type = N’RING_BUFFER_SCHEDULER_MONITOR’
AND record LIKE N’%<SystemHealth>%’) AS x
) AS y
ORDER BY record_id DESC OPTION (RECOMPILE);
-- Look at the trend over the entire period.
-- Also look at high sustained Other Process CPU Utilization values
This query shows the recent CPU utilization
history for your database server, recorded in one-minute increments.
That means it can miss a short spike of CPU activity, but I don’t think
that’s really a big problem. You should be more interested in the trend
over the last four hours than worry about sub minute spikes. The query
gives you CPU utilization by the SQL Server Database Engine, and the
sum of all other processes that are running on the database server (the
“Other Process CPU Utilization” column). This gives you an idea of CPU
pressure caused by SQL Server versus other sources such as management
or monitoring software. Ideally, your mission-critical database servers
are dedicated SQL Server instances with virtually nothing else running
on the machine besides SQL Server. If you see Other Process CPU
Utilization above 5% for a sustained period, you should investigate
what else is using CPU on your database server.
After looking at your CPU utilization history, it
is a good idea to see what is happening with the physical memory at the
operating-system level on your database server. You can do that using
the query shown in Listing 25.
LISTING 25: Operating system memory information
-- Good basic information about OS memory amounts and state
SELECT total_physical_memory_kb, available_physical_memory_kb,
total_page_file_kb, available_page_file_kb,
system_memory_state_desc
FROM sys.dm_os_sys_memory WITH (NOLOCK) OPTION (RECOMPILE);
-- You want to see "Available physical memory is high"
-- This indicates that you are not under external memory pressure
This query tells you how much physical
memory is in the server, how much physical memory is available, how
large the operating system page file is, and how much space is
available in the page file. It also signals whether the operating
system is low on physical memory, which would mean that SQL Server was
under external memory pressure. It is rare to see the operating system
signaling that is under severe memory pressure, especially if you have
set the max server memory (MB) instance-level setting in SQL Server to
an appropriate value that leaves enough memory available for the
operating system.