Skip to content

SQLServer 资源调控器配置

资源调控器概述

SQL Server 资源调控器是一种工作负载管理工具,用于管理 SQL Server 实例的资源使用。它允许 DBA 根据工作负载类型分配 CPU、内存和 I/O 资源,确保关键业务工作负载获得足够的资源,同时防止非关键工作负载消耗过多资源。

资源调控器架构

核心组件

  1. 资源池 (Resource Pool)

    • 定义资源限制,如 CPU 百分比、内存限制等
    • 包括默认池、内部池和用户定义池
    • 控制 CPU、内存和 I/O 资源
  2. 工作负载组 (Workload Group)

    • 包含一组具有相似资源需求的会话
    • 映射到资源池
    • 定义会话级别的资源限制
  3. 分类器函数 (Classifier Function)

    • T-SQL 函数,用于将会话分配到工作负载组
    • 基于会话属性,如登录名、应用程序名称、主机名等
    • 在会话建立时执行
  4. 资源管理器 (Resource Manager)

    • 协调资源池和工作负载组
    • 监控资源使用情况
    • 强制执行资源限制

资源调控器工作原理

  1. 会话建立:用户连接到 SQL Server
  2. 分类:分类器函数执行,将会话分配到工作负载组
  3. 资源分配:会话从工作负载组关联的资源池获取资源
  4. 资源监控:资源管理器监控资源使用情况
  5. 资源限制:强制执行资源池和工作负载组的资源限制

资源调控器配置

步骤 1:启用资源调控器

sql
-- 启用资源调控器
ALTER RESOURCE GOVERNOR RECONFIGURE;

-- 检查资源调控器状态
SELECT * FROM sys.dm_resource_governor_configuration;

步骤 2:创建资源池

sql
-- 创建 CPU 和内存资源池
CREATE RESOURCE POOL [CriticalWorkloadPool]
WITH (
    MIN_CPU_PERCENT = 60,          -- 最小 CPU 百分比
    MAX_CPU_PERCENT = 100,         -- 最大 CPU 百分比
    CAP_CPU_PERCENT = 100,         -- CPU 上限
    AFFINITY SCHEDULER = AUTO,     -- CPU 亲和性
    MIN_MEMORY_PERCENT = 60,       -- 最小内存百分比
    MAX_MEMORY_PERCENT = 100,      -- 最大内存百分比
    CAP_MEMORY_PERCENT = 100       -- 内存上限
);

-- 创建 I/O 资源池(SQL Server 2014 及以上版本)
CREATE RESOURCE POOL [ReportingPool]
WITH (
    MIN_CPU_PERCENT = 20,
    MAX_CPU_PERCENT = 50,
    MIN_MEMORY_PERCENT = 20,
    MAX_MEMORY_PERCENT = 50,
    IOPS_PER_VOLUME = 100,         -- 每卷 IOPS 限制
    MIN_IOPS_PER_VOLUME = 20,      -- 每卷最小 IOPS
    CAP_IOPS_PER_VOLUME = 200      -- 每卷 IOPS 上限
);

步骤 3:创建工作负载组

sql
-- 创建工作负载组
CREATE WORKLOAD GROUP [CriticalWorkloadGroup]
USING [CriticalWorkloadPool]
WITH (
    IMPORTANCE = HIGH,             -- 重要性级别:LOW, MEDIUM, HIGH
    REQUEST_MAX_MEMORY_GRANT_PERCENT = 25, -- 单个请求最大内存授予百分比
    REQUEST_MEMORY_GRANT_TIMEOUT_SEC = 60, -- 内存授予超时(秒)
    MAX_DOP = 8,                   -- 最大并行度
    GROUP_MAX_REQUESTS = 0,        -- 工作负载组最大请求数(0 表示无限制)
    THROTTLING_PRIORITY = 1        -- 限流优先级(1-64,1 最高)
);

-- 创建报告工作负载组
CREATE WORKLOAD GROUP [ReportingGroup]
USING [ReportingPool]
WITH (
    IMPORTANCE = MEDIUM,
    REQUEST_MAX_MEMORY_GRANT_PERCENT = 50,
    REQUEST_MEMORY_GRANT_TIMEOUT_SEC = 120,
    MAX_DOP = 4,
    GROUP_MAX_REQUESTS = 0
);

步骤 4:创建分类器函数

sql
-- 创建分类器函数
CREATE FUNCTION dbo.ResourceGovernorClassifier()
RETURNS sysname
WITH SCHEMABINDING
AS
BEGIN
    DECLARE @WorkloadGroup sysname;
    
    -- 根据应用程序名称分类
    IF APP_NAME() LIKE '%SQL Server Management Studio%' OR APP_NAME() LIKE '%Microsoft SQL Server Management Studio%'
        SET @WorkloadGroup = 'AdministratorGroup';
    
    -- 根据登录名分类
    ELSE IF SUSER_SNAME() = 'sa' OR SUSER_SNAME() LIKE '%Admin%'
        SET @WorkloadGroup = 'AdministratorGroup';
    
    -- 根据主机名分类
    ELSE IF HOST_NAME() = 'ReportServer'
        SET @WorkloadGroup = 'ReportingGroup';
    
    -- 根据应用程序名称分类
    ELSE IF APP_NAME() LIKE '%CriticalApp%'
        SET @WorkloadGroup = 'CriticalWorkloadGroup';
    
    -- 默认分类
    ELSE
        SET @WorkloadGroup = 'default';
    
    RETURN @WorkloadGroup;
END;
GO

-- 注册分类器函数
ALTER RESOURCE GOVERNOR WITH (CLASSIFIER_FUNCTION = dbo.ResourceGovernorClassifier);

步骤 5:应用配置

sql
-- 应用资源调控器配置
ALTER RESOURCE GOVERNOR RECONFIGURE;

-- 验证配置
SELECT * FROM sys.resource_governor_resource_pools;
SELECT * FROM sys.resource_governor_workload_groups;
SELECT * FROM sys.dm_resource_governor_configuration;

资源调控器监控

监控资源池

sql
-- 查看资源池统计信息
SELECT 
    rp.name AS resource_pool_name,
    rp.min_cpu_percent,
    rp.max_cpu_percent,
    rp.min_memory_percent,
    rp.max_memory_percent,
    rps.avg_cpu_percent,
    rps.avg_memory_percent,
    rps.max_memory_used_mb,
    rps.active_session_count
FROM sys.dm_resource_governor_resource_pools rp
JOIN sys.dm_resource_governor_resource_pool_stats rps ON rp.pool_id = rps.pool_id;

监控工作负载组

sql
-- 查看工作负载组统计信息
SELECT 
    wg.name AS workload_group_name,
    rp.name AS resource_pool_name,
    wgs.request_count,
    wgs.active_request_count,
    wgs.total_cpu_usage_ms,
    wgs.total_memory_usage_mb,
    wgs.queued_request_count,
    wgs.max_request_cpu_time_ms
FROM sys.dm_resource_governor_workload_groups wg
JOIN sys.dm_resource_governor_workload_group_stats wgs ON wg.group_id = wgs.group_id
JOIN sys.dm_resource_governor_resource_pools rp ON wg.pool_id = rp.pool_id;

监控会话分类

sql
-- 查看会话分类情况
SELECT 
    s.session_id,
    s.login_name,
    s.host_name,
    s.program_name,
    wg.name AS workload_group_name,
    rp.name AS resource_pool_name
FROM sys.dm_exec_sessions s
JOIN sys.dm_resource_governor_workload_groups wg ON s.group_id = wg.group_id
JOIN sys.dm_resource_governor_resource_pools rp ON wg.pool_id = rp.pool_id
WHERE s.session_id > 50; -- 排除系统会话

资源调控器优化

1. 资源池优化

  • CPU 配置

    • 为关键工作负载分配足够的 MIN_CPU_PERCENT
    • 使用 MAX_CPU_PERCENT 限制非关键工作负载
    • 考虑使用 CAP_CPU_PERCENT 限制突发使用
  • 内存配置

    • 为关键工作负载分配足够的 MIN_MEMORY_PERCENT
    • 使用 MAX_MEMORY_PERCENT 限制非关键工作负载
    • 避免内存过度分配
  • I/O 配置

    • 为 I/O 密集型工作负载设置适当的 IOPS 限制
    • 使用 MIN_IOPS_PER_VOLUME 确保关键工作负载获得足够的 I/O 资源
    • 考虑使用 CAP_IOPS_PER_VOLUME 限制非关键工作负载

2. 工作负载组优化

  • 重要性设置

    • 为关键工作负载设置 IMPORTANCE = HIGH
    • 为非关键工作负载设置 IMPORTANCE = LOWMEDIUM
  • 内存授予设置

    • 为大型查询设置适当的 REQUEST_MAX_MEMORY_GRANT_PERCENT
    • 调整 REQUEST_MEMORY_GRANT_TIMEOUT_SEC 避免查询超时
  • 并行度设置

    • 为 CPU 密集型工作负载设置适当的 MAX_DOP
    • 考虑使用 GROUP_MAX_REQUESTS 限制并发请求数

3. 分类器函数优化

  • 简化分类逻辑

    • 避免复杂的分类逻辑,减少分类开销
    • 优先使用索引列进行分类
    • 考虑使用 APP_NAME()SUSER_SNAME()HOST_NAME() 等内置函数
  • 测试分类准确性

    • 验证会话是否被正确分类
    • 监控分类器函数的执行开销
    • 定期审查分类规则

资源调控器最佳实践

1. 从简单开始

  • 从基本配置开始,逐渐增加复杂性
  • 首先关注 CPU 和内存资源
  • 只对关键工作负载进行分类

2. 监控和调整

  • 定期监控资源使用情况
  • 根据实际负载调整资源池和工作负载组配置
  • 记录配置变更和性能影响

3. 测试配置

  • 在测试环境中测试资源调控器配置
  • 模拟真实工作负载
  • 评估配置对性能的影响

4. 考虑工作负载特性

  • 根据工作负载类型设计资源调控器配置
  • 区分 OLTP 和数据仓库工作负载
  • 考虑批处理和交互式工作负载的差异

5. 结合其他优化技术

  • 结合索引优化和查询优化
  • 考虑使用读写分离
  • 结合 Always On 可用性组

6. 定期审查配置

  • 定期审查资源池和工作负载组配置
  • 审查分类器函数
  • 移除不再需要的配置

常见资源调控器场景

场景 1:OLTP 和数据仓库混合环境

配置建议

  • 创建两个资源池:OLTP 池和数据仓库池
  • OLTP 池:MIN_CPU_PERCENT = 70, MAX_CPU_PERCENT = 100
  • 数据仓库池:MIN_CPU_PERCENT = 30, MAX_CPU_PERCENT = 50
  • 分类器函数根据应用程序名称或数据库名称分类

场景 2:关键业务应用和报告系统

配置建议

  • 创建关键业务应用资源池和报告系统资源池
  • 关键业务应用池:MIN_CPU_PERCENT = 60, MAX_CPU_PERCENT = 100
  • 报告系统池:MIN_CPU_PERCENT = 20, MAX_CPU_PERCENT = 50
  • 分类器函数根据应用程序名称或主机名分类

场景 3:多租户环境

配置建议

  • 为每个租户创建资源池和工作负载组
  • 根据租户级别分配资源
  • 使用分类器函数根据数据库名称或登录名分类

资源调控器故障排查

1. 分类器函数问题

症状:会话未被正确分类或分类开销过大

排查步骤

  1. 检查分类器函数逻辑
  2. 测试分类器函数:
    sql
    SELECT dbo.ResourceGovernorClassifier() AS ClassifiedGroup;
  3. 监控分类器函数执行开销
  4. 简化分类器函数逻辑

2. 资源池配置问题

症状:工作负载未获得足够资源或资源限制过严

排查步骤

  1. 检查资源池配置
  2. 监控资源池统计信息
  3. 调整 MIN_CPU_PERCENTMAX_CPU_PERCENT 设置
  4. 调整内存和 I/O 限制

3. 工作负载组配置问题

症状:查询超时或性能下降

排查步骤

  1. 检查工作负载组配置
  2. 调整 REQUEST_MAX_MEMORY_GRANT_PERCENT 设置
  3. 调整 REQUEST_MEMORY_GRANT_TIMEOUT_SEC 设置
  4. 调整 MAX_DOP 设置

常见问题 (FAQ)

Q1: 资源调控器支持哪些资源类型?

A: SQL Server 资源调控器支持以下资源类型:

  • CPU 资源(所有版本)
  • 内存资源(所有版本)
  • I/O 资源(SQL Server 2014 及以上版本)

Q2: 资源调控器对性能有影响吗?

A: 资源调控器会带来一定的性能开销,主要包括:

  • 分类器函数执行开销
  • 资源监控开销
  • 资源限制强制执行开销

但在大多数情况下,这些开销可以忽略不计,而资源调控器带来的好处远大于开销。

Q3: 如何禁用资源调控器?

A: 可以使用以下命令禁用资源调控器:

sql
-- 禁用资源调控器
ALTER RESOURCE GOVERNOR DISABLE;

-- 检查资源调控器状态
SELECT * FROM sys.dm_resource_governor_configuration;

Q4: 资源调控器可以与 Always On 可用性组一起使用吗?

A: 是的,资源调控器可以与 Always On 可用性组一起使用。需要在每个副本上单独配置资源调控器,或使用中央管理服务器统一配置。

Q5: 如何备份资源调控器配置?

A: 可以使用以下方法备份资源调控器配置:

sql
-- 备份资源调控器配置
SELECT * FROM sys.resource_governor_resource_pools;
SELECT * FROM sys.resource_governor_workload_groups;
SELECT OBJECT_DEFINITION(OBJECT_ID('dbo.ResourceGovernorClassifier')) AS ClassifierFunction;

Q6: 资源调控器支持 Azure SQL Database 吗?

A: Azure SQL Database 提供了类似的功能,称为资源治理,但与 SQL Server 资源调控器的实现有所不同。Azure SQL Database 使用服务级别目标 (SLO) 和资源限制来管理资源。

总结

SQL Server 资源调控器是一种强大的工作负载管理工具,可以帮助 DBA 管理 SQL Server 实例的资源使用。通过合理配置资源池、工作负载组和分类器函数,可以确保关键业务工作负载获得足够的资源,同时防止非关键工作负载消耗过多资源。

建议 DBA 在实施资源调控器时,遵循以下最佳实践:

  1. 从简单配置开始,逐渐增加复杂性
  2. 定期监控资源使用情况,根据实际负载调整配置
  3. 在测试环境中测试配置
  4. 考虑工作负载特性设计配置
  5. 结合其他优化技术
  6. 定期审查配置

通过实施资源调控器,可以提高 SQL Server 实例的资源利用率,确保关键业务工作负载的性能,同时为非关键工作负载提供适当的资源,实现更好的工作负载管理和服务质量。