SQL Server 2014 新特性:IO资源调控

有三种硬件资源一直是影响数据库性能好坏的关键——内存、CPU和物理IO。当服务器上有多个数据库时,极有可能发生资源的争夺,如何能保证在核心库拥有足够资源的前提下再把多余的资源提供给其它数据库呢?这就是资源调控器的作用。

在SQL Server 2014中已经增加了对物理IO资源的控制,这个功能在私有云的数据库服务器上的作用体现得尤为重要,它能够为私有云用户提供有效的控制、分配,并隔离物理IO资源。

 

一、 SQL Server中资源调控器

SQL Server 2014资源调控器默认包含了两个工作负荷组(internal、default)和两个资源池(internal、default),在没有手动设置资源调控器的情况下,创建的数据库会默认放到default资源池当中。

SQL Server资源调控器接收到会话请求后,通过用户定义的分类器函数划分会话并路由到相应的工作负荷组,再通过工作负荷组找到对应的资源池,根据资源池中设置的内存、CPU和物理IO资源阈值来决定会话请求的资源分配。

SQL Server资源调控器逻辑结构图:


 

二、 SQL Server资源调控器运用 —— CPU

接着讲述资源调控器在CPU方面的运用场景:假设数据库服务器上有一个重要的数据库ImportantDB和一个普通的数据库GeneralDB,从业务出发,希望服务器上的资源在满足了ImportantDB之后才考虑分配多余的资源给GeneralDB,保证重要业务系统的正常运行。

  需要说明的是:笔者的机器是Azure上的虚拟机,机器的配置如图5所示,下面的测试都是基于这个环境的,所以读者在自行测试的时候应该根据自己的机器环境进行调整。

假设GeneralDB 可占用的CPU最大值为10%,ImportantDB为90%,实现这个需求的步骤如下:

1. 创建测试数据库

--创建重要业务数据库
CREATE DATABASE ImportantDB;
--创建普通业务数据库
CREATE DATABASE GeneralDB;

 

2. 创建并配置新的资源池和工作负荷组

  • 重要业务数据库
--创建重要业务数据库的资源池
CREATE RESOURCE POOL rpImportantDB
WITH
(
     MAX_CPU_PERCENT = 90,
     MIN_CPU_PERCENT = 10
)
GO

--创建重要业务数据库的工作负荷组
CREATE WORKLOAD GROUP wgImportantDB
WITH
(
     IMPORTANCE = MEDIUM
)
USING rpImportantDB
GO
  • 普通业务数据库
--创建普通业务数据库的资源池
CREATE RESOURCE POOL rpGeneralDB
WITH
(
     MAX_CPU_PERCENT = 10,
     MIN_CPU_PERCENT = 0
)
GO

--创建重要业务数据库的工作负荷组
CREATE WORKLOAD GROUP wgGeneralDB
WITH
(
     IMPORTANCE = LOW
)
USING rpGeneralDB
GO

 

3. 更新内存中资源调控器的配置

--更新内存中的配置
ALTER RESOURCE GOVERNOR RECONFIGURE;

 

4. 查询资源调控器中资源池和工作负荷组的配置信息

--查询获取资源池和工作负荷组配置
USE master
SELECT * FROM sys.resource_governor_resource_pools;
SELECT * FROM sys.resource_governor_workload_groups;

 

5. 创建分类器函数

是一个用户自定义函数,资源调控器用它对会话进行分类以便路由到对应的工作负荷组中,函数返回工作负荷组的名称。

--创建分类器函数
CREATE FUNCTION fn_Classifier()
RETURNS SYSNAME
WITH SCHEMABINDING
AS
BEGIN
    DECLARE @strGroupName SYSNAME
    IF ORIGINAL_DB_NAME()='ImportantDB'
        SET @strGroupName='wgImportantDB'
    ELSE IF ORIGINAL_DB_NAME()='GeneralDB'
        SET @strGroupName='wgGeneralDB'
    ELSE
        SET @strGroupName='default'
    RETURN @strGroupName
END
GO

 

6. 将分类器函数fn_Classifier注册到资源调控器并更新内存中的配置

--注册分类器函数到资源调控器并更新内存中的配置
ALTER RESOURCE GOVERNOR WITH (CLASSIFIER_FUNCTION = dbo.fn_Classifier)
ALTER RESOURCE GOVERNOR RECONFIGURE
GO

 

7. 设置性能计数器监控

Windows为SQL Server资源调控器提供了大量的性能计数器帮助了解资源的使用情况。查看SQLServer:Resource Pool Stats对象下的CPU usage%计数器,里面包括四个对象实例:default、internal和刚刚创建的rpGeneralDB、rpImportantDB。

 

8. 对CPU进行测试

创建能占用CPU的测试脚本,把下面的脚本分别保存为GeneralDB.sql和ImportantDB.sql:

--测试CPU
DECLARE @Counts INT
WHILE 1=1
BEGIN
    SELECT @Counts=COUNT(*) FROM SYS.COLUMNS A,SYS.COLUMNS B
END

SQLCMD调用GeneralDB.sql和ImportantDB.sql脚本:

SQLCMD -S . -d GeneralDB -i GeneralDB.sql
SQLCMD -S . -d ImportantDB -i ImportantDB.sql

性能计数器CPU usage%记录了在测试过程中CPU的使用情况

执行GeneralDB.sql后,蓝色实例rpGeneralDB占用了25%左右的CPU;在另外的窗口执行ImportantDB.sql后,紫色实例rpImportantDB同样占用了25%左右的CPU,以同样的方式继续增加紫色实例rpImportantDB的CPU占用量,当占用量超过了设置的90%,可以发现蓝色实例rpGeneralDB占用CPU百分比马上下降了。从这个测试的结果来看,SQL Server资源调控器已经达到我们预期对CPU资源的规划效果。

大家可能已经发现rpImportantDB资源池的CPU usage%计数器的最新值高达97.470%,资源池不是设置了MAX_CPU_PERCENT = 90吗?怎么会超过这个限制呢?其实这是因为rpGeneralDB资源池的MIN_CPU_PERCENT = 0,在没有其它最小CPU的限制时,rpImportantDB资源池占用的CPU是有可能达到100%的。

 

三、SQL Server资源调控器运用 —— IO

前面讲述关于CPU资源的控制更多的是为下面SQL Server 2014在IO资源上的调控做铺垫,上面的例子是以数据库为单位规划各个库占用CPU的百分比,下面的例子我们就将以登录用户来划分磁盘的IOPS。

假设generalUser用户占用的IOPS最大值为10,importantUser用户占用IOPS的最大值为20,实现这个需求的步骤如下:

 

1. 首先解除分类器函数与资源调控器注册关系

USE [master]
GO
--解除分类器函数注册
ALTER RESOURCE GOVERNOR WITH (CLASSIFIER_FUNCTION = NULL)
GO

 

2. 修改资源池,添加MAX_IOPS_PER_VOLUME和MIN_IOPS_PER_VOLUME属性

--修改重要业务数据库的资源池
ALTER RESOURCE POOL rpImportantDB
WITH
(
     MAX_CPU_PERCENT = 90,
     MIN_CPU_PERCENT = 10,
     MAX_IOPS_PER_VOLUME = 20,
     MIN_IOPS_PER_VOLUME = 0
)
--修改普通业务数据库的资源池
ALTER RESOURCE POOL rpGeneralDB
WITH
(
     MAX_CPU_PERCENT = 10,
     MIN_CPU_PERCENT = 0,
     MAX_IOPS_PER_VOLUME = 10,
     MIN_IOPS_PER_VOLUME = 0
)
GO

3. 修改分类器函数fn_Classifier()

改成按照登录用户:importantUser和generalUser分类,函数返回对应的工作负荷组名称

--修改分类器函数
ALTER FUNCTION fn_Classifier()
RETURNS SYSNAME
WITH SCHEMABINDING
AS
BEGIN
    DECLARE @strGroupName SYSNAME
    IF SUSER_SNAME()='importantUser'
        SET @strGroupName='wgImportantDB'
    ELSE IF SUSER_SNAME()='generalUser'
        SET @strGroupName='wgGeneralDB'
    ELSE
        SET @strGroupName='default'
    RETURN @strGroupName
END
GO

 

4. 重新把分类器函数fn_Classifier()注册到资源调控器并更新内存中的配置

--注册分类器函数到资源调控器并更新内存中的配置
ALTER RESOURCE GOVERNOR WITH (CLASSIFIER_FUNCTION = dbo.fnClassifier)
ALTER RESOURCE GOVERNOR RECONFIGURE
GO

 

5. 创建测试数据

在GeneralDB数据库中创建一个名为TestIOPS的表,并向表中插入10000行记录。

USE [GeneralDB]
GO

--创建表
CREATE TABLE [dbo].[TestIOPS](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [MyStr] [nchar](450) NULL
) ON [PRIMARY]
GO

--插入测试数据
SET NOCOUNT ON;
GO
DECLARE @count INT = 0;
WHILE (@count < 10000)
BEGIN
    INSERT INTO [GeneralDB].[dbo].[TestIOPS](MyStr)
        VALUES(REPLICATE('a',450));
    SET @count +=  1;
END
GO

 

6. 开始测试

1)使用generalUser用户登陆SSMS

通过在TestIOPS表的MyStr字段创建一个非聚集索引来测试IOPS,在执行创建索引的脚本之前,打开性能计数器帮助监控创建索引时的IOPS,找到SQLServer:Resource Pool Stats对象下的Disk Write IO/sec计数器。

USE [GeneralDB]
GO
--创建索引
CREATE NONCLUSTERED INDEX idx_MyStr_1 ON [GeneralDB].[dbo].[TestIOPS] ([MyStr]);
GO

可以看出资源池rpGeneralDB 中Disk Write IO/sec计数器的最大值为10,时间从22:54:52到22:55:02,大概为20秒。

2)使用importantUser用户登陆SSMS

创建上一步骤中一样的索引结构,只需要修改索引名称即可,同样需要监控SQLServer:Resource Pool Stats对象下的Disk Write IO/sec计数器。

USE [GeneralDB]
GO
--创建索引
CREATE NONCLUSTERED INDEX idx_MyStr_2 ON [GeneralDB].[dbo].[TestIOPS] ([MyStr]);
GO

  可以看出资源池rpImportantDB 中Disk Write IO/sec计数器的最大值为20,时间从22:59:52到23:00:11,大概为9秒。

  通过上面资源调控器的IOPS的测试,可以发现即使两个用户执行了相同操作,但IOPS却可以根据不同用户而有所区别,这完全归功于资源调控器对IO资源的控制,这将为数据库主机或者私有云上运行IO密集型工作负载提供解决方案。

 

其他 sqlserver 2014新特性参考:

发布了218 篇原创文章 · 获赞 29 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/Hehuyi_In/article/details/103267731
今日推荐