存储过程在第一次运行时运行缓慢

Posted

技术标签:

【中文标题】存储过程在第一次运行时运行缓慢【英文标题】:Stored procedure runs slow on the first run 【发布时间】:2016-03-10 16:44:02 【问题描述】:

我有一份每天运行并执行数十个存储过程的工作。 它们中的大多数运行良好,但其中一些最近开始需要一段时间才能运行(4-5 分钟)。 当我早上进来并尝试对其进行故障排除时,它们只需要 10-20 秒,就像他们应该做的那样。 过去 10 天左右一直在发生这种情况。未对服务器进行任何更改(我们正在运行 SQL 2012)。 我该如何解决它,我该怎么做才能解决这个问题?? 谢谢!!

【问题讨论】:

您如何排除故障?您是否在 SSMS 中运行它们?他们有参数吗?它可能是参数嗅探。可能是由于数据倾斜,执行计划已达到临界点,并且计划不是最优的。这可能是很多事情。你能发布一个过程并回答我关于调试技术的问题吗? 在 SP 开始减速时有什么变化吗?比如大约在同一时间开始的新工作。 如果只是在第一次运行时速度很慢,那么我肯定会查看您的计划缓存。每当您在 SQL 中运行任何东西时,它都必须进行一些检查以查看它是否已经有计划或需要创建一个计划。如果您的计划缓存过大,则此检查可能会花费比应有的时间更长的时间。另外,您说“第一次运行”,但这是一个反复出现的问题,所以这是服务器重启后的第一次运行还是...? @BobKaufman,我检查了我的 DBA,服务器上似乎没有任何变化,同时没有其他作业在运行。 几乎可以肯定是参数嗅探。它有所有的故事迹象。它在 SSMS 中运行速度很快,但在程序中运行速度很慢。该参数是一个日期时间,这是参数嗅探最常见的问题之一,因为数据量可能如此倾斜。看看 Gail Shaw 的这篇文章。它演示了该问题以及有助于提高性能的几种方法。 sqlinthewild.co.za/index.php/2007/11/27/parameter-sniffing 【参考方案1】:

您可以使用 SQL 提供的一些 DMV(动态管理视图)来调查计划缓存。但是,结果可能有点吓人,而且如果没有一些背景知识,可能很难深入研究结果。我建议查看一些 DMV,例如 sys.dm_exec_query_statssys.dm_exec_cached_plans。 SQLSkills.com 的 Kimberly Tripp 在 Pluralsight 上做了一些很棒的课程,介绍如何使用这些课程,并通过从这些 DMV 构建更高级的查询来获得一些很棒的结果。

同样,这些 DMV 将返回一个 plan_handle 列,您可以将其传递给另一个 DMV sys.dm_exec_query_plan(plan_handle),以返回特定语句的执行计划。困难的部分将是挖掘dm_exec_cached_plans 的结果以找到导致问题的特定作业/存储过程。 sys.dm_exec_sql_text(qs.[sql_handle]) 可以通过提供为该作业运行的 SQL 的快照来提供帮助,但您将通过 CROSS APPLY 与我提到的其他一些 DMV 一起从中获得最大的好处(在我看来)。如果您可以识别 Job/Proc/Statement 并查看计划,它可能会向您显示 Sean Lange 提到的参数嗅探问题的一些迹象。

以防万一:参数嗅探是当您运行查询/存储过程的第一个实例时,SQL 会查看您传入的参数并基于它构建计划。从查询/过程的初始编译生成的计划将非常适合您传入的特定参数,但可能不适用于其他参数。想象一个高度倾斜的表格,其中所有日期都是“01-01-2000”,除了一个是“10-10-2015”。 由于数据的选择性(阅读:数据的唯一性如何?),传入这两个参数会产生截然不同的计划。如果其中一个计划被保存到缓存并在每次后续执行时调用,那么它可能(并且在某些情况下很可能)对于其他参数来说不是理想的。

您看到 Job 与您自己运行命令时的速度不同的可能原因是,当您运行它时,您是在 Ad Hoc 运行它。 Job 不是,它将它们作为存储过程运行,这意味着它们将使用不同的执行计划。

TL;DR: 您为作业保存的执行计划未优化。但是,当您手动运行它时,您可能会创建一个针对特定运行进行优化的 Ad Hoc 计划。挖掘计划缓存并查看发生了什么有点困难,但这是 100% 值得的。我强烈建议您查看 Kimberly Tripp 的博客,因为她有一些关于这方面的精彩文章以及关于 Pluralsight 的一些精彩课程。

【讨论】:

以上是关于存储过程在第一次运行时运行缓慢的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 2008 R2 中运行缓慢的存储过程

SQL Server 索引重新创建存储过程慢

SQL Server 存储过程在第一次运行时需要很长时间

存储过程超时,而后续运行需要 1/6 的时间 [关闭]

SQL Server 存储过程具体解释

编译原理—运行时存储PL0活动记录