SQL Server Resource Governor

,

Introduction

I have a SQL Server that suffers from overnight CPU contention. This system is used in the early hours of the morning so I decided to see what I could do and try to put some order in place by using Resource Governor. I am using SQL Server 2012 Enterprise Edition, so I have this feature available to me, therefore allowing me to specify limits on the amount of CPU that an incoming request can use.

I should state that I cannot change code as this piece of software is a third party product, hence I cannot violate the support agreement. This solution represents a short term control mechanism until the third party make long term changes.

SQL Server Environment

Here is my current SQL Server environment:

  • Windows Server 2008R2 Enterprise – SP1 (64 bit)
  • SQL Server 2012 Enterprise Edition – SP2 (64 bit) – Default Instance used.
  • Processor – Intel(R) Xeon CPU E5-2665 2.40 GHz – 4 cores
  • Memory – 24GB RAM DDR3 – 1333MHZ – This is the amount assigned to MAX Memory on the default instance.

The Problem

Overnight there is a mixture of multiple SQL Server Analysis Services (SSAS) cube processing tasks, DBA maintenance tasks, batch processes and general activity that takes place.  For the purpose of this article I reproduced the situation on an exact pre-production equivalent. As you can see from the below Perfmon graph CPU usage is generally high.

My Aim

I want to throttle down the CPU assigned to SSAS based processes allowing my other tasks to also use CPU during contention, this is because the SSAS tasks has a negative impact on my other workloads.

The Solution

I decided to create two pools, a so-called slow one (called SQLCPUSLOW) and a fast one (called SQLCPUFAST). The SQLCPUSLOW pool was assigned a maximum of 10% of CPU during contention periods and the fast pool I had assigned 90%. Please note, as stated by Boris Baryshnikov, “When you specify percentage on a pool it ensures average CPU bandwidth distribution on per scheduler basis for CPU bound workloads”. (http://blogs.technet.com/b/sqlos/archive/2008/01/18/part-2-resource-governor-cpu-demo-on-multiple-cpus.aspx).

The key element to my solution here is that The MAX_CPU_PERCENT value tells the scheduler how to allocate resources when there is contention between workloads.

T-SQL Setup

Here is the T-SQL I used to set up the Resource Governor pools.

USE master
GO
-- Create Pools
CREATE RESOURCE POOL SQLCPUSLOW
WITH
(
   max_cpu_percent = 10
)
CREATE RESOURCE POOL SQLCPUFAST
WITH
(
   max_cpu_percent = 90
)
GO

The below code then binds the pools created to workload groups.

-- Create groups
CREATE WORKLOAD GROUP SQLCPUFAST
  USING SQLCPUFAST;
GO
CREATE WORKLOAD GROUP SQLCPUSLOW
  USING SQLCPUSLOW;
GO

The next section shows the classifier function, I have put in fake names for obfuscation purposes. What I want to do here is align the SSAS bound work that runs under the DOMAIN\SSASSERVICE to the CPUSQLSLOW pool and my other important batch based tasks and maintenance tasks that runs under DOMAIN\ SQLAGENTSERVICE to my fast pool.

  -- My classifier
IF OBJECT_ID('dbo.DeduceIt','FN') IS NOT NULL
       DROP FUNCTION dbo.DeduceIt
USE master
O
CREATE FUNCTION dbo.DeduceIt()
  RETURNS SYSNAME WITH SCHEMABINDING
AS
BEGIN
      DECLARE @val sysname
      IF 'DOMAIN\SSASSERVICE' = SUSER_SNAME()
             SET @val = 'SQLCPUSLOW';
           
            ELSE IF 'DOMAIN\SQLAGENTSERVICE' = SUSER_SNAME()
                  SET @val = 'SQLCPUFAST';
      RETURN @val;
END
GO
-- Now enable
USE master
GO
ALTER RESOURCE GOVERNOR WITH (CLASSIFIER_FUNCTION = dbo.DeduceIt);
ALTER RESOURCE GOVERNOR RECONFIGURE;

Using the following select statements you can then confirm a successful setup.

-- check Metadata
SELECT * FROM sys.resource_governor_workload_groups
SELECT * FROM sys.resource_governor_resource_pools
SELECT * FROM sys.resource_governor_configuration

The Results

The SSAS tasks now start along with the SQL Agent jobs, batch processes and general activity. This ultimately causes contention; I hope to see resource governor throttle the CPU allocated to SSAS jobs.

First we should check that the classifier is working – looking at the output of the below code snippet I can see that logins are going to the correct pool.

USE master
GO
SELECT sess.session_id, sess.login_name, sess.group_id, grps.name
  FROM sys.dm_exec_sessions AS sess
  JOIN sys.dm_resource_governor_workload_groups AS grps
      ON sess.group_id = grps.group_id
  WHERE session_id > 60;

We will now analyze counters from Perfmon to portray a picture.

The main counters of interest are - SQLServer:Workload Group Stats: CPU Usage % : SQLCPUSLOW and SQLServer:Workload Group Stats: CPU Usage % : SQLCPUFAST.

When contention occurs (approx at 13:37:35) you can see via the yellow line (SQLCPUSLOW pool) that resource governor throttles down the CPU usage for the SSAS tasks, whereas the blue line (middle line) being my SQLCPUFAST POOL has been allowed to use more CPU resource. The red line (top line) shows overall CPU usage.

From analysing the above image I can conclude that I have met my goal. This has allowed me to provide some sort of predictable performance on a server that at times suffers from high CPU usage.

Clean Up

If you need to start again you would use the below T-SQL.

USE master
GO
ALTER RESOURCE GOVERNOR WITH (CLASSIFIER_FUNCTION = null)
GO
ALTER RESOURCE GOVERNOR DISABLE;
USE master
GO
DROP WORKLOAD GROUP SQLCPUFAST
GO
DROP WORKLOAD GROUP SQLCPUSLOW
GO
DROP RESOURCE POOL SQLCPUFAST;
GO
DROP RESOURCE POOL SQLCPUSLOW;
GO
DROP FUNCTION dbo.DeduceIt

Acknowledgments

I would like to thank Raul Gonzalez for reviewing this article.

Rate

4.65 (17)

Share

Share

Rate

4.65 (17)