今天,我偶然发现了一个有趣的性能问题,即在 Sql Server 2005 SP2 上运行的存储过程在兼容级别为 80 (SQL2000) 的数据库中运行。
proc 运行大约 8 分钟,执行计划显示使用了一个实际行数为 1.339.241.423 的索引,这比表本身的“真实”实际行数 1.144.640 高大约 1000 倍,如正确显示通过估计的行数。所以查询计划优化器给出的实际行数肯定是错误的!
有趣的是,当我将 proc 中的 procs 参数值复制到局部变量并在实际查询中使用局部变量时,一切正常 - proc 运行 18 秒,执行计划显示正确的实际行数。
编辑:正如 TrickyNixon 所建议的,这似乎是参数嗅探问题的标志。但实际上,我在这两种情况下都得到了完全相同的执行计划。相同的索引以相同的顺序使用。我看到的唯一区别是直接使用参数值时,PK_ED_Transitions 索引上的实际行数较高。
我已经完成了 dbcc dbreindex 和 UPDATE STATISTICS 没有任何成功。dbcc show_statistics 也显示了良好的索引数据。
proc 是用 RECOMPILE 创建的,因此每次运行时都会编译一个新的执行计划。
更具体地说 - 这个运行速度很快:
CREATE Proc [dbo].[myProc](
@Param datetime
)
WITH RECOMPILE
as
set nocount on
declare @local datetime
set @local = @Param
select
some columns
from
table1
where
column = @local
group by
some other columns
这个版本运行速度非常慢,但产生完全相同的执行计划(除了已用索引上的实际行数过高):
CREATE Proc [dbo].[myProc](
@Param datetime
)
WITH RECOMPILE
as
set nocount on
select
some columns
from
table1
where
column = @Param
group by
some other columns
有任何想法吗?有谁知道 Sql Server 在计算查询计划时从哪里获得实际的行计数值?
更新:我在另一台服务器上尝试了查询,将 copat 模式设置为 90(Sql2005)。它的行为相同。我想我会打开一个 ms 支持电话,因为这在我看来就像一个错误。