Search This Blog

Saturday, April 21, 2018

SQL Script to Monitor CPU Utilization

This post helps you in understanding and using SQL Script to Monitor CPU utilization. There are certain scenarios where we can quickly use this script to get SQL Server CPU utilization.
  • When there is a performance issue, and you need to quickly check the CPU usage
  • When doing Root Cause Analysis
  • When we only have access to SQL Server not to Windows

SQL Server CPU Utilization history report for last N minutes:

Below is the SQL Script to Monitor CPU utilization. This script captures the CPU usage history report from last 10 min. This can be customized by changing the variable “@lastNmin” value.

SQL Server Database wise CPU Utilization

From above script we come to know that SQL Server is utilizing high CPU, now the next step is to find out which database from the SQL instance is causing the high CPU utilization. Below is the SQL Script to Monitor CPU Utilization database wise.

SQL Server Query Wise CPU Utilization

From the above scripts you confirmed that there is a huge CPU utilization from one of the SQL Instance and you identified the database which is causing high CPU. Now the next step is to identify top 10 queries which are causing high CPU utilization. Here is the SQL Script to Monitor CPU Utilization query level. This is a wonderful script provided by SQLBlog and SQLKnowlwdge.
Note: Remember that it returns the list of costly queries which causes high CPU utilization when only the CPU usage is >=80% from last 10 Min, otherwise it returns nothing. You can modify the script as per your needs.

Script to find Top 20 Costliest Stored Procedures – High CPU:

 This script sourced from here. It results a list of stored procedures which are utilizing high CPU. This script goes through the buffer cache and find out these results based on Total and Average worker thread times. Below is the SQL Script to Monitor CPU Utilization from the stored procedure point of view.

Script to find Top 20 Costliest Queries – High CPU

 This script sourced from here. It results a list of queries which are utilizing high CPU. Below is the SQL Script to Monitor CPU Utilization from Ad-hoc queries.

Multiple SQL Query Output in CSV

Approach: We will create a table with multiple columns of any name with datetype as varchar to store any value. Once table is created we will insert the columns header of  the output of your first query then insert the results of the first query. Follow same steps for other queries you want to execute.

For better understanding please check below queries

CREATE TABLE [dbo].[tblABC](
[A] [varchar](200) NULL, [B] [varchar](200) NULL, [C] [varchar](200) NULL, [D] [varchar](200) NULL, [E] [varchar](200) NULL,
[F] [varchar](200) NULL, [G] [varchar](200) NULL, [H] [varchar](200) NULL, [I] [varchar](200) NULL, [J] [varchar](200) NULL,
[K] [varchar](200) NULL, [L] [varchar](200) NULL, [M] [varchar](200) NULL, [N] [varchar](200) NULL, [O] [varchar](200) NULL,
[P] [varchar](200) NULL, [Q] [varchar](200) NULL, [R] [varchar](200) NULL, [S] [varchar](200) NULL, [T] [varchar](200) NULL,
[U] [varchar](200) NULL, [V] [varchar](200) NULL, [W] [varchar](200) NULL, [X] [varchar](200) NULL, [Y] [varchar](200) NULL,
[Z] [varchar](200) NULL
) ON [PRIMARY]
GO


Declare @aa varchar(100)
set @aa =cast(getdate() as varchar)

INSERT INTO [dbo].[tblABC] (A)
(Select 'Report Generated on  '+ @aa)


INSERT INTO [dbo].[tblABC] (A) Values
('Server :  ' + @@SERVERNAME)
INSERT INTO [dbo].[tblABC] (A) Values
('Instance  :  '+ @@SERVICENAME)

INSERT INTO [dbo].[tblABC] (A) values
(' ')

INSERT INTO [dbo].[tblABC] (A) values
('>>>>>>>>>>>>>Instance Logins<<<<<<<<<<<<<<<')

INSERT INTO [dbo].[tblABC] (A) values
(' ')

INSERT INTO [dbo].[tblABC] (A,B,C) Values
('name','dbname','language')

INSERT INTO [dbo].[tblABC] (A,B,C)
(select name,dbname,language  from syslogins)

INSERT INTO [dbo].[tblABC] (A) values
(' ')

INSERT INTO [dbo].[tblABC] (A) values
('>>>>>>>>>>>>>Database details<<<<<<<<<<<<<<<')

INSERT INTO [dbo].[tblABC] (A) values
(' ')

INSERT INTO [dbo].[tblABC] (A,B,C,D,E,F,G,H,I,J) Values
('name','database_id','create_date','compatibility_level','collation_name','user_access_desc','state_desc',
'snapshot_isolation_state','recovery_model','recovery_model_desc')

INSERT INTO [dbo].[tblABC] (A,B,C,D,E,F,G,H,I,J)
(Select name,database_id,create_date,compatibility_level,collation_name,user_access_desc,state_desc,snapshot_isolation_state,
recovery_model,recovery_model_desc from sys.databases)

Inserted Data will look like this

Select * from [dbo].[tblABC]


To avoid null run below query

SELECT isnull([A] ,'') as A      ,isnull([B] ,'') as B      ,isnull([C] ,'') as C      ,isnull([D] ,'') as D      ,isnull([E] ,'') as E
      ,isnull([F] ,'') as F      ,isnull([G] ,'') as G      ,isnull([H] ,'') as H      ,isnull([I] ,'') as I      ,isnull([J] ,'') as J
      ,isnull([K] ,'') as K      ,isnull([L] ,'') as L      ,isnull([M] ,'') as M      ,isnull([N] ,'') as N      ,isnull([O] ,'') as O
      ,isnull([P] ,'') as P      ,isnull([Q] ,'') as Q      ,isnull([R] ,'') as R      ,isnull([S] ,'') as S      ,isnull([T] ,'') as T
      ,isnull([U] ,'') as U      ,isnull([V] ,'') as V      ,isnull([W] ,'') as W      ,isnull([X] ,'') as X      ,isnull([Y] ,'') as Y
      ,isnull([Z] ,'') as Z
  FROM [master].[dbo].[tblABC]

Output will be like this



Now run below query in PowerShell which will export above data to CSV and skip the columns named A,B,C,D......

$Query = "
SELECT isnull([A] ,'') as A      ,isnull([B] ,'') as B      ,isnull([C] ,'') as C      ,isnull([D] ,'') as D
      ,isnull([E] ,'') as E      ,isnull([F] ,'') as F      ,isnull([G] ,'') as G      ,isnull([H] ,'') as H
      ,isnull([I] ,'') as I      ,isnull([J] ,'') as J      ,isnull([K] ,'') as K      ,isnull([L] ,'') as L
      ,isnull([M] ,'') as M      ,isnull([N] ,'') as N      ,isnull([O] ,'') as O      ,isnull([P] ,'') as P
      ,isnull([Q] ,'') as Q      ,isnull([R] ,'') as R      ,isnull([S] ,'') as S      ,isnull([T] ,'') as T
      ,isnull([U] ,'') as U      ,isnull([V] ,'') as V      ,isnull([W] ,'') as W      ,isnull([X] ,'') as X
      ,isnull([Y] ,'') as Y      ,isnull([Z] ,'') as Z
  FROM [master].[dbo].[tblABC]
"
$filee="C:\"+"$(get-date -f MM-dd-yyyy)_Report.csv"
write-host $filee
$results = Invoke-SQLcmd -Server CHRV4204 -Database master -Query $Query |
ConvertTo-Csv -NoTypeInformation |Select-Object -Skip 1 |Set-Content -Path $filee

Above script can be execute as job in SQL Server as below



To send attachment via email you can use below script

declare @aa varchar(333) set @aa= convert(varchar, getdate(), 110) select @aa = 'C:\Data\' + @aa + '_Report.csv' select @aa EXEC msdb.dbo.sp_send_dbmail @profile_name = 'TestMailprofile', @recipients ='youremail@gmail.com', @subject = 'test', @body = 'hi', @importance = 'HIGH', @file_attachments = @aa, @body_format ='HTML' --because

In Excel your output will be like this



Find SQL Server Port

DECLARE @InstanceName nvarchar(50)
DECLARE @value VARCHAR(100)
DECLARE @RegKey_InstanceName nvarchar(500)
DECLARE @RegKey nvarchar(500)

SET @InstanceName=CONVERT(nVARCHAR,isnull(SERVERPROPERTY('INSTANCENAME'),'MSSQLSERVER'))

--For SQL Server 2000
if(SELECT Convert(varchar(1),(SERVERPROPERTY('ProductVersion'))))=8
BEGIN
if @InstanceName='MSSQLSERVER'
Begin
SET @RegKey='SOFTWARE\Microsoft\'+@InstanceName+'\MSSQLServer\SuperSocketNetLib\TCP\'
END
ELSE
BEGIN
SET @RegKey='SOFTWARE\Microsoft\Microsoft SQL Server\'+@InstanceName+'\MSSQLServer\SuperSocketNetLib\TCP\'
END

EXECUTE xp_regread
  @rootkey = 'HKEY_LOCAL_MACHINE',
  @key = @RegKey,
  @value_name = 'TcpPort',
  @value = @value OUTPUT

Select @@SERVERNAME as ServerName,@value as PortNumber
END

--For SQL Server 2005 and up
if(SELECT Convert(varchar(1),(SERVERPROPERTY('ProductVersion'))))<>8
BEGIN
SET @RegKey_InstanceName='SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL'

EXECUTE xp_regread
  @rootkey = 'HKEY_LOCAL_MACHINE',
  @key = @RegKey_InstanceName,
  @value_name = @InstanceName,
  @value = @value OUTPUT

SET @RegKey='SOFTWARE\Microsoft\Microsoft SQL Server\'+@value+'\MSSQLServer\SuperSocketNetLib\TCP\IPAll'

EXECUTE xp_regread
  @rootkey = 'HKEY_LOCAL_MACHINE',
  @key = @RegKey,
  @value_name = 'TcpPort',
  @value = @value OUTPUT

Select @@SERVERNAME as ServerName,@value as PortNumber
END

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
OR


DECLARE @InstName VARCHAR(16)

DECLARE @RegLoc VARCHAR(100)

SELECT @InstName = @@SERVICENAME

IF @InstName = 'MSSQLSERVER'
  BEGIN
    SET @RegLoc='Software\Microsoft\MSSQLServer\MSSQLServer\SuperSocketNetLib\Tcp\'
  END
 ELSE
  BEGIN
   SET @RegLoc='Software\Microsoft\Microsoft SQL Server\' + @InstName + '\MSSQLServer\SuperSocketNetLib\Tcp\'
  END

EXEC [master].[dbo].[xp_regread] 'HKEY_LOCAL_MACHINE', @RegLoc, 'tcpPort'

Tuesday, December 20, 2016

Important Links

Powershell

https://www.simple-talk.com/sql/database-administration/the-posh-dba-accessing-sql-server-from-powershell/

To run 70 queries on server to check everything

http://www.sqlstad.nl/

To find linked server password

https://github.com/NetSPI/Powershell-Modules/blob/master/Get-MSSQLLinkPasswords.psm1

awesome free tools

https://dbatools.io/getting-started/