我有一个存储过程用于包含 62 个使用 UNION ALL 的子查询的 DI 报告。最近,性能从不到 1 分钟增加到超过 8 分钟,使用 SQL Profiler,它显示出非常高的 CPU 和读取。该过程当前已将变量设置为局部变量以防止参数嗅探。
将过程的内容作为 SELECT 语句运行,性能恢复到不到一分钟。 在 Management Studio 中通过 EXEC 调用程序,性能非常糟糕,超过 8 分钟。 通过 EXEC 调用过程,包括 WITH RECOMPILE 命令和性能没有提高。我运行了 DBCC FREEPROCCACHE 和 DBCC DROPCLEANBUFFERS,但仍然没有任何改善。
最后,我放弃了程序并重新应用它,现在性能又回来了。
谁能帮我解释一下为什么最初的步骤没有纠正程序的性能,但放弃并重新应用程序却可以?
最佳答案
听起来阻塞参数嗅探产生了一个糟糕的计划。当您使用局部变量时,查询优化器使用每列的密度来得出基数估计值,本质上是针对平均值进行优化。如果您的数据分布明显偏斜,则对于某些值,此估计值将显着偏离。这个理论解释了为什么您的初始步骤不起作用。如果参数嗅探被阻止,使用 WITH RECOMPILE 或运行 DBCC FREEPROCCACHE 将无济于事。它每次都会产生相同的计划。因为您说将过程的内容作为 SELECT 语句运行使其更快,所以我认为您实际上需要参数嗅探。但是,如果编译时间可以接受,您还需要尝试使用 WITH RECOMPILE,否则有可能陷入基于原始嗅探值的错误计划。
关于sql-server - SQL 性能 : Recompile versus drop and re-apply for stored procedure,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17224571/