SQL Server – Script to Check Plan Cache Bloat

SQL Server will look at each query and check if it has a plan cache already compiled for.  If it has, then it will reuse the plan in the cache. If it does not have, then an execution plan is compiled and added to the plan cache.

When identical queries ran over many times, its plan will be reused. This will save resources from having to compile repeatedly.

Now what happens when you have hundreds or thousands of different queries that are only executed once? In this case there are no execution plan to be reused. This is what we call PLAN CACHE BLOAT.

Plan cache bloat is bad because it steals memory from the buffer pool that are better used for database pages. When you execute the script  below, and if you see “Adhoc” Cache type to be on top, then that means that there are a lot of queries that are executed once and are causing plan cache bloat.

 

SELECT 
    objtype AS [CacheType]
    , count_big(*) AS [Total Plans]
    , sum(cast(size_in_bytes as decimal(18,2)))/1024/1024 AS [Total MBs]
    , avg(usecounts) AS [Avg Use Count]
    , sum(cast((CASE WHEN usecounts = 1 THEN size_in_bytes ELSE 0 END) as decimal(18,2)))/1024/1024 AS [Total MBs - USE Count 1]
    , sum(CASE WHEN usecounts = 1 THEN 1 ELSE 0 END) AS [Total Plans - USE Count 1]
FROM 
    sys.dm_exec_cached_plans
GROUP BY 
    objtype
ORDER BY 
    [Total MBs - USE Count 1] DESC
GO

 

Plan cache bloat can be prevented by enabling “Optimize for Adhoc Workloads” by only caching the full execution plan of queries that are known to be used more than once.

To enable the optimize for ad hoc workloads setting, use sp_configure, as shown below.

EXEC sp_configure 'show advanced options',1
RECONFIGURE
EXEC sp_configure 'optimize for ad hoc workloads',1
RECONFIGURE
Knowledge worth sharing...Share on linkedin
Linkedin
Share on facebook
Facebook
Share on google
Google
Share on twitter
Twitter

SQL Server – Check if “Enforce Password Policy” is On Using TSQL

The T-SQL query below will check if “Enforce Password Policy” is On. A value of 1 under is_policy_checked column indicates that it is turned on. Otherwise, it is disabled.

select name, is_policy_checked 
from sys.sql_logins 
Knowledge worth sharing...Share on linkedin
Linkedin
Share on facebook
Facebook
Share on google
Google
Share on twitter
Twitter

SQL Server – The EXECUTE permission was denied on the object ‘xp_instance_regread’, database ‘mssqlsystemresource’,schema ‘sys’ (Error 229)

One of our users encountered the error below.

I was able to fix the problem by granting the user direct access to the procedure.

 

USE master
GO

GRANT EXECUTE ON [sys].[xp_instance_regread] TO [DOMAIN\USER];

--To veriy that the user has been granted the privilege
EXECUTE AS USER = 'DOMAIN\USER';Select * from fn_my_permissions('xp_instance_regread','Object')

Knowledge worth sharing...Share on linkedin
Linkedin
Share on facebook
Facebook
Share on google
Google
Share on twitter
Twitter

SQL Server – Get CPU Usage History for last 256 minutes

The other day, I was asked by our Application Team Lead to check why the CPU usage is very high in the Production DB server. It remained consistently high throughout the day. He asked whether it is coming from SQL Server or other processes.

 

 

Below is a useful script to review the CPU usage history for last 256 minutes (This will work on SQL Server 2008 and up)​​ 

 

 

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);

 

 

Now, if the value in “Other Process CPU Utilization (%)” column is higher​​ than​​ “SQL Server Process CPU”, then you may​​ ask​​ your sys admins to investigate the cause. But in our case, it​​ was indicated​​ clearly that the cause of high CPU usage was coming from SQL Server Process.​​ Below is the output of the​​ script.

 

 

 

After seeing the results, I investigated from the SQL queries perspective and found out that there are few​​ expensive queries that are​​ causing high CPU usage. ​​ How did I find out? That would be the subject of another blog.​​ 

Knowledge worth sharing...Share on linkedin
Linkedin
Share on facebook
Facebook
Share on google
Google
Share on twitter
Twitter

SQL Server – Agent Job Fails with Error: Unable to connect to SQL Server ‘(local)’. The step failed

I was​​ checking one of our client’s DB server for the first time.​​ I noticed a​​ couple of their SQL Agent Jobs have been failing due to the error “Unable to connect to SQL Server ‘(local)’”

 

 

 

The reason for this error is because the Database (drop down box) to run the step from is empty.

 

 

 

The solution is to choose the relevant database to run the job step against.

 

Knowledge worth sharing...Share on linkedin
Linkedin
Share on facebook
Facebook
Share on google
Google
Share on twitter
Twitter

SQL Server – Resolve Error 5030 to Rename Database

When you want to rename your database and you hit the error below, you need to set the database to​​ Single User Mode. After you rename your database, then you set the database back to Multi-User mode.​​

Msg 5030, Level 16, State 2, Line 1

The database could not be​​ exclusively locked to perform the operation

Follow the steps​​ below to rename your database.​

  1. Set the database to single-mode
ALTER DATABASE OLD_DBName SET SINGLE_USER WITH ROLLBACK IMMEDIATE;

2. Rename the Database

ALTER DATABASE OLD_DBName MODIFY NAME = NEW_DBNAME;

3. Set the database to Multi-user mode

ALTER DATABASE NEW_DBNAME SET MULTI_USER WITH ROLLBACK IMMEDIATE;

You may check out this blog post where I show a better way to rename a database.

Cheers!

Knowledge worth sharing...Share on linkedin
Linkedin
Share on facebook
Facebook
Share on google
Google
Share on twitter
Twitter

SQL Server – SQL Server Agent Job History

The other day, I was troubleshooting a database slowness issue when the lead application developer asks me whether or not there are any SQL Jobs running during that time. The T-SQL​​ script below helped me to retrieve that info. This T-SQL script will check the SQL Agent Job history.

 

 

SELECT

​​ j.name​​ AS​​ 'JobName',

​​ run_date,

​​ run_time,

​​ msdb.dbo.agent_datetime(run_date,​​ run_time)​​ AS​​ 'RunDateTime'

FROM​​ msdb.dbo.sysjobs j​​ 

INNER​​ JOIN​​ msdb.dbo.sysjobhistory h​​ 

​​ ON​​ j.job_id​​ =​​ h.job_id​​ 

WHERE​​ j.enabled​​ =​​ 1 ​​ --Only Enabled Jobs

ORDER​​ by​​ JobName,​​ RunDateTime​​ DESC