今天我在兼容级别为80(SQL2000)的数据库中运行在Sql Server 2005 SP2上运行的存储过程时偶然发现了一个有趣的性能问题.
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支持电话,因为这对我来说就像一个bug.
好的,最后我自己做到了.
这两个查询计划在一个小细节上是不同的,我最初错过了.慢速使用嵌套循环运算符将两个子查询连接在一起.和的结果在当前行高数计数上的索引扫描运算符,其是简单地multiplicating输入的行数与输入B的行数的结果.
我仍然不知道为什么优化器决定使用嵌套的循环,而不是它运行1000计时器在这种情况下,更快的哈希匹配的,但我可以通过创建一个新的索引处理我的问题,从而使发动机不索引查找斯塔特而不是嵌套循环下的索引扫描.