相同(?)SQL Server 2005 机器;一个查询需要 2 秒,另一个需要 15 分钟

rya*_*nki 12 sql-server-2005 sql-server

环境:

我们有两台运行 SQL Server 2005 的 32 位 Windows Server 2003 R2 机器。硬件配置是相同的服务器,具有 Xeon 5160 CPU、4GB RAM 和 13GB RAID0。未启用 AWE 和 /3GB 标志。

服务器是使用预定义的安装清单并排设置的,并且两台机器上安装的所有软件都是相同的。

我们知道要检查的每个 SQL 服务器安装设置和补丁级别都是相同的。一个区别是 TEMPDB 在快速机器上为 400MB,而在慢速机器上为 1.2GB。但是,在这两种情况下,我们都没有看到任何 TEMPDB 分配发生。

问题:

有一个存储过程,一个运行 2 秒,另一个运行 15 分钟。在额外的 15 分钟内,几乎没有磁盘活动,也没有内存使用变化,但一个 CPU 内核始终保持 100% 固定。

即使从一个数据库备份并恢复到另一个数据库,这种行为仍然存在。

由于它是一个存储过程,因此活动监视器和分析器不会向我们显示有关此高 CPU 活动在存储过程中的何处发生的任何详细信息。

问题:

我们还应该看什么?

跟进:

缓慢发生在以下游标定义的 FETCH NEXT 语句中:

DECLARE C CURSOR FOR
    SELECT X, Y
    FROM dbo.A
    WHERE X NOT IN (SELECT X FROM dbo.B)
    AND Z <=0
...
<snip>
...
FETCH NEXT FROM C INTO @X, @Y
FETCH NEXT FROM C INTO @X, @Y
...
Run Code Online (Sandbox Code Playgroud)

每个 FETCH 语句——在一个仅包含大约 1000 行的表上——需要大约 7.25 分钟。(不,我不知道为什么它会连续执行两次,需要询问开发人员,但它确实可以在两台服务器上正确运行)。

我对“NOT IN (SELECT ...)”有点怀疑,因为看起来虚拟读取真的很高。

Rem*_*anu 7

使用诸如等待和队列之类的性能故障排除方法来确定高 CPU 消耗的原因,然后在确定瓶颈后建议采取适当的措施。


gbn*_*gbn 6

SQL Server 正在另一个框中选择不同的计划。

恢复通常会根据统计数据消除问题,因此我会查看服务器差异。

首先进行一些粗略的检查。不要假设:检查

  • 检查sys.configuration中的 SQL Server 设置是否相同,例如 Max degree 或 parallelism
  • 运行 DBCC USEROPTIONS 以查看运行时是否有任何 ANSI 设置不同(ANS 设置会影响所选计划)
  • 检查 Windows 和 SQL Server 日志以查看是否存在任何问题

然后按照 Remus 的回答跳到最深处。


Mar*_*ith 6

如果所有其他条件都相同,则很可能(根据@gbn 的回答)在每个服务器上生成不同的执行计划。作为一项学术练习,看到这两个计划会很有趣,因此从每个服务器上的计划缓存中获取它们,并在可能的情况下将它们添加到您的问题中。然后,我们可以确定导致性能如此巨大差异的计划差异。

要快速修复,请查看USE PLAN 提示。这使得将好的计划从快速服务器附加到慢速服务器上的存储过程成为可能。

编辑:以下更新:游标

您的查询的另一种变体尝试我在其他答案中没有提到:

DECLARE C CURSOR FOR
    SELECT X, Y
    FROM dbo.A
    WHERE NOT EXISTS (SELECT 1 FROM dbo.B WHERE dbo.B.X = dbo.A.X)
    AND Z <=0
...
<snip>
...
FETCH NEXT FROM C INTO @X, @Y
FETCH NEXT FROM C INTO @X, @Y
Run Code Online (Sandbox Code Playgroud)