同一存储过程的不同执行计划

时间:2009-02-03 04:18:35

标签: sql sql-server sql-server-2005 stored-procedures sql-execution-plan

我们的生产系统有一个约5秒的查询,但是我们的镜像系统(尽可能与生产相同)和开发系统需要不到1秒。

我们检查了查询计划,我们可以看到它们有所不同。同样从这些计划中我们可以看出为什么一个人比另一个人服用更长时间。数据,schame和服务器类似,存储过程相同。

我们知道如何通过重新安排连接和添加提示来修复它,但是目前如果我们不必对SProc(文书工作)进行任何更改会更容易。我们还尝试了一个sp_recompile。

什么可能导致两个查询计划之间的差异?

系统:Win2k3 Enterprise上的SQL 2005 SP2 Enterprise

更新:感谢您的回复,结果证明这是统计数据。见下面的摘要。

6 个答案:

答案 0 :(得分:12)

您的统计信息很可能已过期。如果数据相同,请重新计算两台服务器上的统计信息并重新编译。然后,您应该看到相同的查询计划。

另外,请仔细检查您的索引是否相同。

答案 1 :(得分:3)

是数据&镜像和生产之间的数据大小尽可能接近相同? 如果你知道为什么一个查询比另一个更长?你能发布更多细节吗?

由于表格和/或统计数据中的数据,执行计划在这种情况下可能会有所不同。即使在启用自动更新统计信息的情况下,统计信息也会过时(特别是在非常大的表中) 您可能会发现优化器估计表不是那么大,并选择了表扫描或类似的东西。

答案 2 :(得分:3)

最有可能是统计数据。

一些想法: 你对非产品系统进行维护吗? (例如,重建索引,将重建统计数据)

如果是,您使用相同的填充因子和统计样本比率吗?

您是否定期将数据库恢复到测试中,这样100%就像生产一样?

答案 3 :(得分:2)

如果您的proc上没有WITH RECOMPILE选项,则执行计划将在首次执行后进行缓存。

以下是一个简单的示例,说明如何缓存错误的查询计划:

create proc spTest
    @id int 
as 
select * from sysobjects where @id is null or id = id 

go 

exec spTest null
-- As expected its a clustered index scan

go

exec spTest 1
-- OH no its a clustered index scan 

尝试在存储过程之外的生产服务器上的QA中运行Sql,以确定您的统计信息是否过时或生产中缺少神秘索引的问题。

答案 4 :(得分:2)

在第一个答案中,问题可能在于SQL Server的参数嗅探功能。它使用导致编译的第一个值来帮助创建执行计划。通常这很好,但如果价值不正常(或某种程度上是奇怪的),它可能导致糟糕的计划。这也可以解释生产和测试之间的区别。

关闭参数嗅探需要修改我理解的SProc是不受欢迎的。但是,在使用sp_recompile之后,传入您认为“正常”的参数,并且应该根据这些新参数重新编译。

我认为参数嗅探行为在2005年到2008年之间是不同的,所以这可能不起作用。

答案 5 :(得分:0)

解决方案是重新计算统计数据。我忽略了这一点,因为通常我们已安排任务来完成所有这些工作,但由于某种原因,管理员没有把这个服务器放在一个,Doh。

总结所有帖子:

  • 检查设置是否相同
    • 索引
    • 表格大小
    • 还原数据库
  • 执行计划缓存
    • 如果查询在SProc外部运行相同,则不是执行计划
    • sp_recompile如果不同
    • 参数嗅探
  • 重新计算统计数据