sql-server - 有趣的 SQL Server 性能调优问题

标签 sql-server sql-server-2005

我已经研究一个存储过程性能问题一个多星期了,该问题与我在 Stackoverflow 上的其他帖子 here 相关。 。让我给你一些背景信息。

我们有一个每晚运行的进程,并由一个存储过程启动,该存储过程调用许多其他存储过程。许多被调用的存储过程调用其他存储过程,等等。我查看了一些被调用的过程,其中有各种令人恐惧的复杂内容,例如 XML 字符串处理、不必要的游标过度使用、过度使用 NOLOCK 提示,很少使用基于集合的处理等 - 这样的例子不胜枚举,非常可怕。

我们生产环境中的这个每晚流程平均需要 1 分 15 秒才能运行。有时需要2个小时才能运行,这是 Not Acceptable 。我在与生产相同的硬件上创建了一个测试环境并运行该过程。我第一次运行花了45分钟。如果我将数据库恢复到完全相同的点并再次运行它,则需要更长的时间:事实上,如果我多次重复此操作(恢复并重新运行),该过程将花费越来越长的时间,直到在 2 小时左右达到稳定状态。这真的让我很困惑,因为我每次都将数据库恢复到完全相同的点。服务器上没有其他用户数据库。

我想到了两条线索:

  1. 查询计划和参数欺骗
  2. 临时数据库

作为测试,我重新启动 SQL Server 以清除缓存和 tempdb,并使用相同的数据库恢复重新运行过程。该过程耗时 45 分钟。我重复了几次以确保它是可重复的 - 同样每次都需要 45 分钟。然后,我开始进行多项测试,尝试隔离 SQL Server 未重新启动时令人费解的运行时间增加:

  1. 使用 RECOMPILE 运行初始存储过程

  2. 在运行过程之前,执行DBCC FREEPROCCACHE以清除过程缓存

  3. 在运行该过程之前,先执行 CHECKPOINT,然后执行 DBCC DROPCLEANBUFFERS,以确保缓存为空且干净

  4. 执行以下脚本以确保所有存储过程都被标记为重新编译:

    DECLARE @proc_schema SYSNAME
    DECLARE @proc_name SYSNAME
    
    DECLARE prcCsr CURSOR local
        FOR SELECT  specific_schema,
                    specific_name
            FROM    INFORMATION_SCHEMA.routines
            WHERE   routine_type = 'PROCEDURE'
    
    OPEN prcCsr
    
    FETCH NEXT FROM prcCsr INTO @proc_schema, @proc_name
    
    DECLARE @stmt NVARCHAR(MAX)
    WHILE @@FETCH_STATUS = 0
        BEGIN
            SET @stmt = N'exec sp_recompile ''[' + @proc_schema + '].['
                + @proc_name + ']'''
    --        PRINT @stmt   -- DEBUG
            EXEC ( @stmt
                )
    
            FETCH NEXT FROM prcCsr INTO @proc_schema, @proc_name
        END
    

在所有上述测试中,使用相同的数据库还原运行该过程所需的时间越来越长。我现在真的不知道该尝试什么。此时查看代码是一种选择,但实际上需要 3-6 个月才能进行优化,因为那里还有很大的改进空间。我真正感兴趣的是,为什么每次执行数据库恢复时,即使过程和缓冲区缓存已被清理,过程执行时间也会变长?

我也调查了 tempdb,并尝试清除其中的旧表,如我的其他 stackoverflow 帖子中所述,但我无法手动清除从表变量手动创建的临时表,而且它们似乎没有想要自行消失(即使在离开它们 24 小时后)。

任何有关进一步测试的见解或建议将不胜感激。我在 Windows 2003 R2 Ent 上运行 SQL Server 2005 SP3 64 位企业版。版本集群。

问候, 马克。

最佳答案

可能导致此问题的一件事是进程是否泄漏 XML 文档。这将导致 SQL Server 使用更多内存,并且部分内存可能会写入磁盘上的页面文件,从而导致进程变慢。

创建 XML 文档的代码如下所示:

EXEC sp_xml_preparedocument @idoc OUTPUT, @strXML

如果没有对应就会泄漏:

EXEC sp_xml_removedocument @idoc

XML 文档是存储在配置的 SQL Server 内存之外的 COM 对象。即使您将 SQL Server 设置为最多使用 5 GB,泄漏的 XML 文档也会使内存使用量超出此范围。

关于sql-server - 有趣的 SQL Server 性能调优问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1612414/

相关文章:

SQL 乘法后丢失小数

sql-server - Sql Server 2016 "The Parameter Is Incorrect"数据库图表上的外键

sql - 为什么这个触发器改变了我的查询速度?

sql - .sql 文件的存储过程

sql-server - 什么是每秒刷新的日志字节数

c# - SQL连接字符串和cant参数visual studio 2013

sql-server - 无法登录 mssql-server-linux 容器中的 SQL Server

SQL Server查询使用BETWEEN过滤器带来不匹配的数据

sql-server - 无法开始分布式事务

sql-server - 服务器触发器在 SQL Server 中保存在哪里?