写这篇文章的目的是想记录此次的撰写文章的经历,其实一篇技术文章来得并不容易,以前本身写博客的随意性很强,排版能够根据本身喜爱,可是一篇文章要被你们所接受,让你们愿意读完实际上是一件很难的事情,因此排版仍是挺重要的,这里我想提示下IT168的编辑,个人SQL代码实际上是有高亮的,可是编辑发出来后发现高亮不见,阅读起来的确很不爽,估计你们也有一样的感受。再者就是讲讲此次的技术内容,其实在SQL Server 2014以前就有资源调控器这个功能了,因此网上也很多这方面的资料,因此要写这个主题就须要找到一些新的亮点(新功能+通俗类比),这也是读者感兴趣的地方。我对写这篇文章还有一个感觉就是,你须要不断修改、完善你文章的内容,包括总体文章的架构是否合理?语言描述是否通顺?逻辑是否清晰?内容是否丰富?测试案例是否全面等等。因此这篇文章给我最大的感觉是:一篇凭良心出品的文章的确来之不易。html
2014年5月7日,从宋沄剑宋大侠得知有一个为IT168和微软撰写SQL Server 2014新功能文章的机会,撰写的内容为:SQL Server 2014的资源调控器(Resource Governor),这里再次感谢宋大侠的推荐。sql
特此说明:因为版权的缘由,这里的正文为引用IT168的稿件地址:http://tech.it168.com/a2014/0526/1627/000001627131_all.shtml数据库
【IT168 专稿】在数据库服务器上,有三种硬件资源一直是影响数据库性能好坏的关键,甚至会影响到整个生产系统的使用,这三种资源分别是内存、CPU和物理IO。当数据库服务器上挂载了多个数据库的时候,极有可能发生资源的争夺,如何能保证重要数据库在拥有足够资源的前提下再把多余的资源提供给其它数据库呢?资源调控器应运而生。api
在SQL Server 2014中已经增长了对物理IO资源的控制,这个功能在私有云的数据库服务器上的做用体现得尤其重要,它可以为私有云用户提供有效的控制、分配,并隔离物理IO资源。服务器
在讲述SQL Server 2014的资源调控器(Resource Governor)以前,让咱们来找一找生活中资源调控器的影子。你们都知道一线城市的交通能够用拥堵一词来形容,你时常能够见到如图1所示的路面情况。框架
为了缓解拥堵的交通,北京、上海、广州等城市都修建了一个称之为BRT的交通设施,BRT的全称为Bus Rapid Transit,意为快速公交,就是在拥堵的公路上分配一条专门提供给公交车使用的车道,尽可能保证大部分人出行的通畅。BRT专用车道的大体状况如图2所示。性能
交通部门规定:在出行高峰期,BRT专用道只供公交车使用,其它机动车只能使用BRT专用道以外的车道资源。人有专门的人行道,自行车有自行车道。根据这个逻辑,能够得出如图3所示的人与车在使用道路资源的逻辑结构图:
了解了生活中的资源调控器以后,咱们立刻进入今天的主题:SQL Server资源调控器,它与生活中的资源调控器有着惊人的类似之处。
SQL Server 2014的资源调控器默认包含了两个工做负荷组(internal、default)和两个资源池(internal、default),在没有手动设置资源调控器的状况下,建立的数据库会默认放到default资源池当中。
SQL Server资源调控器接收到会话请求后,经过用户定义的分类器函数把会话进行划分并路由到相应的工做负荷组,再经过工做负荷组找到对应的资源池,由资源池中设置的内存、CPU和物理IO资源的阀值来决定会话请求的资源分配。根据描述,能够得出如图4所示的SQL Server资源调控器逻辑结构图:
理解了SQL Server资源调控器的原理以后,接着讲述资源调控器在CPU方面的运用场景:假设数据库服务器上有一个重要的数据库ImportantDB和一个普通的数据库GeneralDB,从业务出发,但愿服务器上的资源在知足了ImportantDB以后才考虑分配多余的资源给GeneralDB,保证重要业务系统的正常运行。
须要说明的是:笔者的机器是Azure上的虚拟机,机器的配置如图5所示,下面的测试都是基于这个环境的,因此读者在自行测试的时候应该根据本身的机器环境进行调整。
假设GeneralDB 数据库占用的CPU最大值为10%,ImportantDB数据库占用的CPU最大值为90%,实现这个需求的步骤以下:
1. 建立测试数据库
--建立重要业务数据库 CREATE DATABASE ImportantDB GO --建立普通业务数据库 CREATE DATABASE GeneralDB GO
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 GO
4. 查询资源调控器中资源池和工做负荷组的配置信息,返回结果如图6所示:
--查询获取资源池和工做负荷组配置 USE master SELECT * FROM sys.resource_governor_resource_pools SELECT * FROM sys.resource_governor_workload_groups GO
5. 建立分类器函数,这是一个用户自定义函数 (UDF),它供资源调控器用来对会话进行分类,以便将它们路由到对应的工做负荷组中,函数返回工做负荷组的名称;
--建立分类器函数 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. 接下来就是对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
8. Windows操做系统为SQL Server资源调控器提供了大量的性能计数器帮助了解资源的使用状况,查看SQLServer:Resource Pool Stats对象下的CPU usage%计数器,里面包括四个对象实例:default、internal和刚刚建立的rpGeneralDB、rpImportantDB,如图7所示:
9. 由于分类器函数fn_Classifier 经过函数ORIGINAL_DB_NAME()返回用户在数据库链接字符串中指定的数据库名称,因此能够经过使用SQLCMD来模拟用户输入,SQLCMD调用GeneralDB.sql和ImportantDB.sql脚本的命令以下:
SQLCMD -S . -d GeneralDB -i GeneralDB.sql
SQLCMD -S . -d ImportantDB -i ImportantDB.sql
10. 性能计数器CPU usage%记录了在测试过程当中CPU的使用状况,结果如图8所示:
执行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%的。
前面讲述关于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. 接着,修改rpImportantDB、rpGeneralDB资源池,添加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. 使用generalUser用户登录SSMS,经过在TestIOPS表的MyStr字段建立一个非汇集索引来测试IOPS,在执行建立索引的脚本以前,打开性能计数器帮助监控建立索引时的IOPS,找到SQLServer:Resource Pool Stats对象下的Disk Write IO/sec计数器,计数器监控的结果如图9所示:
USE [GeneralDB] GO --建立索引 CREATE NONCLUSTERED INDEX idx_MyStr_1 ON [GeneralDB].[dbo].[TestIOPS] ([MyStr]); GO
从图9能够看出资源池rpGeneralDB 中Disk Write IO/sec计数器的最大值为10,发生Disk Write IO/sec的时间从22:54:52持续到22:55:02,持续时间大概为20秒;
7. 接着,使用importantUser用户登录SSMS,建立上一步骤中同样的索引结构,只须要修改索引名称便可,一样须要监控SQLServer:Resource Pool Stats对象下的Disk Write IO/sec计数器,计数器监控的结果如图10所示:
USE [GeneralDB] GO --建立索引 CREATE NONCLUSTERED INDEX idx_MyStr_2 ON [GeneralDB].[dbo].[TestIOPS] ([MyStr]); GO
从图10能够看出资源池rpImportantDB 中Disk Write IO/sec计数器的最大值为20,发生Disk Write IO/sec的时间从22:59:52持续到23:00:11,持续时间大概为9秒;
经过上面资源调控器的IOPS的测试,能够发现即便两个用户执行了相同操做,但IOPS却能够根据不一样用户而有所区别,这彻底归功于资源调控器对IO资源的控制,这将为数据库主机或者私有云上运行IO密集型工做负载提供解决方案。
资源调控器(Resource Governor)在没有资源争夺的时候,那么运用能够分配到100%资源,若是达到了分类器函数的临界值,会按照预先分配的比例进行调配,从而保证重要业务在资源紧缺的状况下顺利进行,加强对数据库的管理性。SQL Server 2014的新功能中提供了一个很是重要的IO资源控制,这将为私有云用户提供更人性化的管理和服务。
陈畅亮,微软SQL Server最有价值专家,目前就任于广州某互联网公司任数据库团队Leader,专一于数据库解决方案与性能调优。