ALTER存储过程(无任何更改)会使它的运行速度慢20倍

时间:2019-03-11 19:47:20

标签: sql sql-server sql-server-2017

我一直在对执行批量插入的存储过程进行一些速度测试。它使用一些JSON作为参数,创建一个表变量,从目标表中已有的表变量中清除表变量中的所有重复项,然后将数据从表变量复制到目标表中。

在运行这些测试时,我看到一些截然不同的速度结果使我发疯。他们没有道理。我终于解决了这个问题,并且能够始终如一地重现它。

流程如下:

  1. 删除目标表中的所有数据
  2. 运行存储过程并传递50,000行的JSON记录
  3. 它执行大约1.5秒。
  4. 重复该过程。这次,它具有需要解析的现有数据以查找重复项。结果相同。不到2秒
  5. 重复N 4次,总是得到相同的结果。
  6. 在SP上运行ALTER而不更改SP本身
  7. 重复步骤4。这次需要30-40秒!
  8. 删除目标表中的数据,重复所有步骤,得到相同的结果。

我一直在学习参数嗅探,尝试诸如将传入的参数转换为本地参数并添加WITH RECOMPILE之类的事情,但是到目前为止,结果都是一样的。

如果这在生产中发生,那将是不可接受的。有人有什么想法吗?

谢谢!

1 个答案:

答案 0 :(得分:4)

发表评论的时间有点长。

SQL Server首次运行时会将查询计划缓存在存储过程中。在您的情况下,第一次运行有一个空表,因此查询计划基于一个空表。对于您的问题,这似乎是一个不错的查询计划。

更改存储过程时,确实会产生一种效果:它会忘记缓存的查询计划。因此,将生成一个新计划,该计划将使用表的当前大小。

无论出于何种原因,第二个查询计划都比第一个查询计划差很多。我不知道为什么通常问题是相反的(空表上的查询计划更糟)。

我建议您弄清楚如何在有数据的情况下使查询具有正确的计划,并在每次运行时重新编译存储过程中的代码。那可能是过大了,但是却增加了一点开销。