存储过程如何有多个执行计划?

How can a stored proc have multiple execution plans?

我正在使用 MS SQL Server 2008 R2。我有一个名为 rpt_getWeeklyScheduleData 的存储过程。这是我用来在特定数据库中查找其执行计划的查询:

select 
   *
from 
   sys.dm_exec_cached_plans cp
      CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) st
where 
   OBJECT_NAME(st.objectid, st.dbid) = 'rpt_getWeeklyScheduleData' and 
   st.dbid = DB_ID()

以上查询returns我9行。我期待 1 行。

此存储过程已被多次修改,所以我相信 SQL 服务器在每次修改时都在为其构建新的执行计划 运行。是正确的解释吗?如果不是,那你怎么解释呢?

还有可以查看每个计划的创建时间吗?如果是那么如何?

更新:

这是存储过程的签名:

CREATE procedure [dbo].[rpt_getWeeklyScheduleData]
(
   @a_paaipk        int,
   @a_location_code int,
   @a_department_code   int,
   @a_week_start_date   varchar(12),
   @a_week_end_date varchar(12),
   @a_language_code int,
   @a_flag      int 
)
as
begin
   ...
end

存储过程很长;对于 @a_flag 参数,只有 2 个 if 条件。

if @a_flag = 0
begin
   ...
end 

if @a_flag = 1
begin
   ...
end

根据存储过程的性质(未提供),出于多种原因(很可能不限于以下),这是很有可能的:

  1. proc是否使用了很多if this then this select, else this select/update
  2. proc 是否包含动态 sql?
  3. 您是否同时从 Web 和 SSMS 执行 SP?那么您可能会使用不同的连接设置执行 SP。
  4. 存储过程有参数吗?有时参数的差异会导致一个执行计划对特定集合来说很糟糕,因此使用不同的计划。

尝试一个可能有帮助的类比...也许...


假设您有一个周末购物的存储过程。 您通常需要购买杂货,有时需要购买空气过滤器,甚至更不用说一大包每年需要更换 4 次的东西。

  1. 杂货店可以处理杂货,离你家最近(5分钟)。
  2. Target 可以处理空气过滤器 杂货,但增加 25 分钟的旅行时间。
  3. "Big place of everything" 拥有您可能需要的一切,但需要一个小时的车程。

所以在这里,根据您的参数 @needsAirFilter@needsBigPackOfSomething 可能会极大地改变 "execution plan" 的 "shopping".

存储过程

如果 @needsAirFilter@needsBigPackOfSomethingfalse,则没有理由进行 30 分钟或小时的车程,因为您需要的一切都在杂货店。

一个月一次,@needsAirFilter是真的,那我们就要去Target了,杂货店的执行计划不够

一年 4 次 @needsBigPackOfSomething 是真的,我们需要花一个小时的时间去买一大包东西,同时还要买杂货和空气过滤器,因为我们在那里。

当然...我们可以每小时开车每个 买杂货的时间,以及其他需要的东西(想象一下单一的执行计划)。但这绝不是最有效的方法。在这种情况下,我们对 information/goods 实际需要的内容有不同的执行计划。

不知道这是否有帮助...但我玩得很开心:D

通常SQL服务器会根据传入的参数值生成一个新的查询计划(这可以确定它将使用哪些索引,如果有的话)以及索引是否被添加、更改或已更新(在 proc 中使用的 tables/views 上)因此 SQL 服务器可能会决定使用一个或多个先前忽略的索引更有效。 SQL 在 proc 中涉及的越多,也会在 SQL 服务器端开始更多的工作,因为它会尝试优化查询。如果数据发生变化(突然间你在新泽西州有更多的客户并且有州的查询和索引)它可能会决定它要使用该索引并且查询计划会改变。如果查询中涉及的任何表或视图更改(架构更改)也将使现有计划无效并导致生成新计划。