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


12

环境:

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

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

我们知道要检查的每个SQL Server安装设置和补丁程序级别都是相同的。一个区别是,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
...

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

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


如何在dbo.B中记录并为dbo.BX编制索引?
Mark Storey-Smith,

1
我很好奇,如果这样做会导致性能差异:从dbo.a中选择dbo.ax,dbo.ay。在dbo.ax = dbo.bx上选择左外部连接dbo.b,其中dbo.bx为null,并且z <= 0
DForck42

再加上一个想法。您确定减速是由于游标提取引起的吗?您是从执行计划(全部与估计有关)还是从配置文件跟踪中确定?
Mark Storey-Smith,

它来自配置文件跟踪。
ryandenki 2011年

执行计划是否相同?其中之一可能使用了错误的执行计划。
赞恩

Answers:



6

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

还原通常会根据统计信息消除问题,因此,我将研究服务器差异。

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

  • 检查SQL Server设置在同一个sys.configuration例如最大程度或并行
  • 运行DBCC USEROPTIONS以查看运行时是否有任何ANSI设置不同(ANS设置会影响所选计划)
  • 检查Windows和SQL Server日志以查看是否存在任何问题

然后按照雷木思的回答跳到最深处。


感谢您的提示。两台机器之间的系统配置和DBCC USEROPTIONS都相同。任何Windows或SQL Server日志中都没有错误或警告。

1
而且它们还运行相同的数据库布局吗?没有管理计划对索引进行优化(索引重建等),数据库对相关对象具有相同的统计信息,并且磁盘布局相同吗?补丁级别相同?
TomTom

是的,磁盘,数据库布局和补丁程序级别相同。实际上,快速计算机上的数据库是缓慢计算机上的还原备份。据我所知,没有任何管理计划会有所不同。
ryandenki 2011年

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

这是一个很好的建议,我们正在检查查询计划。实际上,存储过程的速度降低似乎与游标有关。参见编辑。
ryandenki 2011年

4

幽默一点,尝试更换:

DECLARE C CURSOR FOR
SELECT X, Y
FROM dbo.A
WHERE X NOT IN (SELECT X FROM dbo.B)
AND Z <=0

有了这个:

DECLARE C CURSOR FOR
SELECT 
    X, 
    Y
FROM dbo.A

    LEFT OUTER JOIN dbo.B
        ON dbo.A.X = dbo.b.X

WHERE dbo.B.X IS NULL
AND Z <=0

我不认为这应该在代码的FETCH NEXT FROM部分中表现为性能问题,但是我还没有注射咖啡因。尝试一下我的建议,然后告诉我。

希望这可以帮助,

马特


4

检查索引并更新所有统计信息。我遇到了一个非常类似的问题,事实证明一台计算机上的统计数据很奇怪。


1

我已经经历过两次相同的行为,我将告诉您每次修复该问题的原因:

1.)我向存储过程添加了WITH RECOMPILE提示,因为缓存的计划很糟糕。

2.)我将存储过程更改为使用临时表而不是表变量。

我希望这些帮助。祝好运。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.