修改目标恢复时间 (TARGET_RECOVERY_TIME
) 可以显著影响 SQL Server 的性能,特别是在高并发或高事务负载的场景中。通过将目标恢复时间设为更短的时间(如 1 秒),SQL Server 会更加频繁地执行检查点操作,从而减少事务日志的积压,这可能会提升整体性能。
以下是为什么和如何通过调整 TARGET_RECOVERY_TIME
来影响性能的详细说明,以及进一步优化性能的建议。
1 为什么修改 TARGET_RECOVERY_TIME
会提升性能
- 减少检查点间隔:
- 将目标恢复时间设置为较短时间(如 1 秒)后,SQL Server 会更加频繁地执行检查点操作。检查点会将脏页从内存刷到磁盘,从而减少事务日志的积压。
- 更高的日志写入效率:
- 频繁的检查点操作会减少事务日志中未刷新的记录量,从而提高事务日志写入的效率,减少事务提交时的延迟。
- 减少事务日志增长:
- 较短的目标恢复时间会导致事务日志文件增长得更慢,因为脏页更快地被刷到磁盘,从而减少日志文件的物理增长频率。
如何进一步优化性能
- 监控和调整
TARGET_RECOVERY_TIME
:
- 虽然将目标恢复时间设置为 1 秒提升了性能,但这会增加磁盘 I/O 负担。需要监控系统的 I/O 性能,确保磁盘不会成为新的瓶颈。
- 适当调整目标恢复时间,找到性能和 I/O 负载之间的最佳平衡点。
- 硬件优化:
- 使用高速存储(如 SSD)来进一步提高检查点和日志写入的效率。
- 确保有足够的内存来缓存更多的脏页,从而减少频繁的磁盘写入。
- 索引优化:
- 确保索引设计合理,避免不必要的索引和碎片化,减少事务处理和查询的开销。
- 查询优化:
- 分析和优化查询计划,减少长时间运行的查询对系统资源的占用。
- 使用性能调优工具如 SQL Server Profiler 或扩展事件 (Extended Events) 识别性能瓶颈。
- 配置调整:
- 确保最大内存和最大并行度设置合理,不会导致资源竞争。
- 优化 tempdb 配置,如增加 tempdb 文件数量和合理设置文件增长选项。
示例代码和监控
检查当前 TARGET_RECOVERY_TIME
设置
USE [tpcc];
GO
SELECT name, target_recovery_time_in_seconds
FROM sys.databases
WHERE name = 'tpcc';
调整 TARGET_RECOVERY_TIME
USE [master];
GO
ALTER DATABASE [tpcc] SET TARGET_RECOVERY_TIME = 5 SECONDS WITH NO_WAIT;
GO
监控 I/O 性能
使用动态管理视图监控磁盘 I/O 性能,确保新的设置没有造成 I/O 瓶颈:
SELECT
database_id,
file_id,
io_stall_read_ms,
io_stall_write_ms,
num_of_reads,
num_of_writes,
io_stall_read_ms / num_of_reads AS avg_read_stall,
io_stall_write_ms / num_of_writes AS avg_write_stall
FROM
sys.dm_io_virtual_file_stats(NULL, NULL)
WHERE
database_id = DB_ID('tpcc');
检查索引和统计信息
确保索引和统计信息最新,避免查询性能问题:
USE [tpcc];
GO
-- 更新统计信息
EXEC sp_updatestats;
-- 检查索引碎片
SELECT
DB_NAME() AS DbName,
OBJECT_NAME(ps.object_id) AS TableName,
i.name AS IndexName,
ps.index_id,
avg_fragmentation_in_percent
FROM
sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'DETAILED') AS ps
JOIN sys.indexes AS i ON ps.object_id = i.object_id AND ps.index_id = i.index_id
WHERE
avg_fragmentation_in_percent > 30; -- 阈值根据需要调整
总结
修改 TARGET_RECOVERY_TIME
可以显著提升 SQL Server 性能,特别是在高事务负载环境下。通过频繁的检查点操作,减少了事务日志的积压和写入延迟。然而,需要注意的是,这会增加磁盘 I/O 负担,因此需要监控和调整设置,以找到最佳平衡点。此外,通过硬件优化、索引和查询优化、以及合理的配置调整,可以进一步提升整体性能。
在 SQL Server 中,将 TARGET_RECOVERY_TIME
设置为 0 秒有特殊的含义。TARGET_RECOVERY_TIME
参数用于指定 SQL Server 执行恢复操作(例如从崩溃中恢复数据库)时的目标时间。设置该参数可以影响检查点操作的频率,从而间接影响数据库的性能。
2 TARGET_RECOVERY_TIME
设置为 0 秒的含义
当 TARGET_RECOVERY_TIME
设置为 0 秒时,SQL Server 会使用默认的恢复时间目标,这通常是 1 分钟。这意味着 SQL Server 将根据默认的恢复时间目标来确定检查点的频率,而不进行任何自定义调整。
配置和解释
- 默认恢复时间:当
TARGET_RECOVERY_TIME
设置为 0 秒时,SQL Server 会使用默认的恢复时间目标(1 分钟)。这表示 SQL Server 会尝试确保数据库在崩溃后可以在 1 分钟内恢复。 - 检查点频率:默认恢复时间目标会使 SQL Server 根据工作负载和事务日志的生成量,自动确定检查点操作的频率。这种配置通常适用于大多数标准工作负载。
示例代码
设置 TARGET_RECOVERY_TIME
为 0 秒(使用默认恢复时间目标):
USE [master];
GO
ALTER DATABASE [tpcc] SET TARGET_RECOVERY_TIME = 0 SECONDS WITH NO_WAIT;
GO
影响和建议
- 性能平衡:使用默认恢复时间目标(1 分钟)通常会在性能和数据保护之间提供良好的平衡。它既不会过于频繁地执行检查点操作(从而增加磁盘 I/O 负担),也不会让事务日志积压过多(从而影响恢复时间)。
- 监控和调整:在大多数情况下,默认恢复时间目标是适用的。但如果你的数据库有特殊需求,比如高并发、高事务量或极高的数据可靠性要求,你可能需要调整
TARGET_RECOVERY_TIME
以优化性能和恢复能力。
进一步优化
即使设置了 TARGET_RECOVERY_TIME
,仍然可以通过以下方法进一步优化数据库性能:
- 监控 I/O 性能:使用动态管理视图和性能监控工具,确保磁盘 I/O 性能不会成为瓶颈。
SELECT
database_id,
file_id,
io_stall_read_ms,
io_stall_write_ms,
num_of_reads,
num_of_writes,
io_stall_read_ms / num_of_reads AS avg_read_stall,
io_stall_write_ms / num_of_writes AS avg_write_stall
FROM
sys.dm_io_virtual_file_stats(NULL, NULL);
- 优化查询和索引:定期检查和优化查询执行计划,确保索引和统计信息是最新的。
-- 更新统计信息
EXEC sp_updatestats;
-- 检查索引碎片
SELECT
DB_NAME() AS DbName,
OBJECT_NAME(ps.object_id) AS TableName,
i.name AS IndexName,
ps.index_id,
avg_fragmentation_in_percent
FROM
sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'DETAILED') AS ps
JOIN sys.indexes AS i ON ps.object_id = i.object_id AND ps.index_id = i.index_id
WHERE
avg_fragmentation_in_percent > 30;
- 硬件升级:考虑使用更高性能的存储设备(如 SSD)和增加内存,以提升整体性能。
- 配置调整:根据具体的工作负载需求,调整最大并行度 (MAXDOP)、最大内存设置等配置参数。
总结
将 TARGET_RECOVERY_TIME
设置为 0 秒意味着使用 SQL Server 的默认恢复时间目标(1 分钟)。这种设置通常适用于大多数标准工作负载,提供了性能和恢复能力之间的良好平衡。如果你的数据库有特殊的性能或恢复要求,可以根据具体情况调整该参数,并结合其他优化方法来提升整体性能
SQL Server 2016 将默认的 TARGET_RECOVERY_TIME
设置为 60 秒,以在性能和数据恢复之间提供更好的平衡。相比之下,SQL Server 2014 的默认值为 0 秒,更多地关注性能优化。
3 使用数据库触发器自动设置 TARGET_RECOVERY_TIME
在 SQL Server 2016 中,每次创建新的数据库时,默认的目标恢复时间 (TARGET_RECOVERY_TIME
) 为 60 秒。要使新创建的数据库具有不同的默认恢复时间(例如,0 秒),需要使用数据库触发器来自动设置该值。
可以创建一个 DDL 触发器,这个触发器在数据库创建时自动运行,并将新创建的数据库的 TARGET_RECOVERY_TIME
设置为 0 秒。
以下是步骤:
- 创建触发器:在
master
数据库中创建一个触发器,该触发器会在每次创建数据库时自动执行设置TARGET_RECOVERY_TIME
的命令。 - 触发器逻辑:触发器会捕获新创建的数据库名称,并执行
ALTER DATABASE
命令来设置TARGET_RECOVERY_TIME
为 0 秒。
示例代码
以下是实现上述逻辑的示例代码:
sql
复制代码
USE master;
GO
-- 如果已经存在名为 SetTargetRecoveryTime 的触发器,先将其删除
IF EXISTS (SELECT * FROM sys.server_triggers WHERE name = 'SetTargetRecoveryTime')
BEGIN
DROP TRIGGER SetTargetRecoveryTime ON ALL SERVER;
END;
GO
-- 创建新的触发器
CREATE TRIGGER SetTargetRecoveryTime
ON ALL SERVER
FOR CREATE_DATABASE
AS
BEGIN
DECLARE @DatabaseName NVARCHAR(128);
-- 从事件数据中获取新创建的数据库名称
SET @DatabaseName = EVENTDATA().value('(/EVENT_INSTANCE/DatabaseName)[1]', 'NVARCHAR(128)');
-- 动态 SQL 设置目标恢复时间为 0 秒
DECLARE @sql NVARCHAR(MAX);
SET @sql = N'ALTER DATABASE [' + @DatabaseName + N'] SET TARGET_RECOVERY_TIME = 0 SECONDS WITH NO_WAIT;';
-- 执行动态 SQL
EXEC sp_executesql @sql;
END;
GO
触发器的工作原理
- 事件捕获:触发器捕获
CREATE_DATABASE
事件。 - 获取数据库名称:从事件数据中提取新创建的数据库名称。
- 设置恢复时间:构建并执行
ALTER DATABASE
命令,将新数据库的TARGET_RECOVERY_TIME
设置为 0 秒。
验证触发器
创建一个新的数据库,检查其 TARGET_RECOVERY_TIME
是否为 0 秒:
sql
复制代码
-- 创建新数据库
CREATE DATABASE TestDB;
GO
-- 检查新数据库的 TARGET_RECOVERY_TIME
SELECT name, target_recovery_time_in_seconds
FROM sys.databases
WHERE name = 'TestDB';
GO
-- 清理测试数据库
DROP DATABASE TestDB;
GO
总结
通过创建一个服务器级的 DDL 触发器,可以自动将新创建数据库的 TARGET_RECOVERY_TIME
设置为 0 秒。这种方法确保所有新创建的数据库都符合你的恢复时间目标需求,无需手动设置。触发器在创建新数据库时自动运行,使管理员的工作更加高效和一致。