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/

Sunday, July 19, 2015

5 minutes SSAS Admin for SQL DBAs

Often, a SQL DBA has to administer SSAS. Here’s a quick 5 mins guide.
  1. How to process a cube?In SSMS, right click cube name, process, OK.
  1. When was the cube last processed?File, New, DMX query, select  * from $system.mdschema_cubes
  1. Who is using the cube right now?File, New, DMX query, select * from $system.discover_connection
  1. How do I give a user access to the cube?Put the user into a new AD group. In SSMS, + on CubeName, right click Role, new role, Membership, Add, type the AD group name, click Cubes on the left pane, Access = Read
  1. How big is the cube?The size of this folder: C:\Program Files\Microsoft SQL Server\MSAS11.SSAS_MD\OLAP\Data\CubeName.0.db
    Easier but less accurate: in SSMS, right click cube name, properties, Estimated Size.
  1. How do I deploy cube changes to production?In Dev server, right click the Cube name, script database as, create, new window. Change the <Database Name? to “x_New”, and the connection string (Search “ConnectionString” to find it). Save it as x.xmla. Change connection to Production, F5 to execute the script. Right click the new cube, Process, OK. After the new cube is processed, delete the old cube and rename the new cube.
    If you have secondary Prod server, use Synchronize: right click the cube on SSMS, Synchronize. This will copy SSAS files from Secondary Server to Primary Server incrementally (only changed files are copied). You need to process the cube first in the Secondary Server.
  1. How long does it take to process the cube?Open SQL profiler, File, new trace, specify SSAS server, Event: Progress Report Begin and End, column filter: DatabaseName like xxx.
  1. How do I process a cube every night?In SSMS, right click cube name, process, script. Create a new SQL Agent job, new job step, type = AS Command, command = paste the script.
  1. How do I track who’s using the cube every day?Setup query log table. See this article: link
  1. Server spec for SSAS?Start with 16 GB, quad core, 100 GB disk. That should be ok for cube size 5-10 GB.
  1. How do I limit what each user can see in the cube?In SSMS, + on Cube Name, right click Role, new role, Dimension Data, select the dimension, tick the number you want the users to see.
  1. Error when processing the cube: the attribute key was not found.In SSDT, in Solution Explorer pane, double click the Dimension, look at the DSV panel. Make sure all the dimension key values in the fact table exist in the dimension table. If your dimension is made up of 2 tables chained together, make sure the referenced value exist in the referenced table.
  1. How do I find out the MDX of the query?Install OLAP Pivot Table Extension: link (thanks to Greg Galloway)
  1. How do I browse a cube?
    In SSMS, right click the cube name (not the database name), Browse.
    Better: open Excel, Data menu, From Other Sources, Analysis Services, type the SSAS Server Name, Next, select the cube name, Finish.
  1. How do I query the cube data using SQL?
    select * from openquery(LinkedServer1, ‘select Measure1 on columns from Cube1′).
    LinkedServer1 is setup as Provider: OLE DB for SSAS 11, Product Name: MSOLAP.5, Data source: AS Server Name, Catalog: AS DB Name.
  1. The cube is very slow
    Put a trace on SQL Profiler to capture all MDX that hit the cube. Find the long running MDX. Optimize using cube partitioning, aggregation, look at cell-by-cell calculation, check cell-based security, check server memory, use cache warming, don’t process the cube during office hours.