存储过程如何有多个执行计划?
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
根据存储过程的性质(未提供),出于多种原因(很可能不限于以下),这是很有可能的:
- proc是否使用了很多
if this then this select, else this select/update
- proc 是否包含动态 sql?
- 您是否同时从 Web 和 SSMS 执行 SP?那么您可能会使用不同的连接设置执行 SP。
- 存储过程有参数吗?有时参数的差异会导致一个执行计划对特定集合来说很糟糕,因此使用不同的计划。
尝试一个可能有帮助的类比...也许...
假设您有一个周末购物的存储过程。
您通常需要购买杂货,有时需要购买空气过滤器,甚至更不用说一大包每年需要更换 4 次的东西。
- 杂货店可以处理杂货,离你家最近(5分钟)。
- Target 可以处理空气过滤器 和 杂货,但增加 25 分钟的旅行时间。
- "Big place of everything" 拥有您可能需要的一切,但需要一个小时的车程。
所以在这里,根据您的参数 @needsAirFilter
和 @needsBigPackOfSomething
可能会极大地改变 "execution plan" 的 "shopping".
存储过程
如果 @needsAirFilter
和 @needsBigPackOfSomething
是 false
,则没有理由进行 30 分钟或小时的车程,因为您需要的一切都在杂货店。
一个月一次,@needsAirFilter
是真的,那我们就要去Target了,杂货店的执行计划不够
一年 4 次 @needsBigPackOfSomething
是真的,我们需要花一个小时的时间去买一大包东西,同时还要买杂货和空气过滤器,因为我们在那里。
当然...我们可以每小时开车每个 买杂货的时间,以及其他需要的东西(想象一下单一的执行计划)。但这绝不是最有效的方法。在这种情况下,我们对 information/goods 实际需要的内容有不同的执行计划。
不知道这是否有帮助...但我玩得很开心:D
通常SQL服务器会根据传入的参数值生成一个新的查询计划(这可以确定它将使用哪些索引,如果有的话)以及索引是否被添加、更改或已更新(在 proc 中使用的 tables/views 上)因此 SQL 服务器可能会决定使用一个或多个先前忽略的索引更有效。 SQL 在 proc 中涉及的越多,也会在 SQL 服务器端开始更多的工作,因为它会尝试优化查询。如果数据发生变化(突然间你在新泽西州有更多的客户并且有州的查询和索引)它可能会决定它要使用该索引并且查询计划会改变。如果查询中涉及的任何表或视图更改(架构更改)也将使现有计划无效并导致生成新计划。
我正在使用 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
根据存储过程的性质(未提供),出于多种原因(很可能不限于以下),这是很有可能的:
- proc是否使用了很多
if this then this select, else this select/update
- proc 是否包含动态 sql?
- 您是否同时从 Web 和 SSMS 执行 SP?那么您可能会使用不同的连接设置执行 SP。
- 存储过程有参数吗?有时参数的差异会导致一个执行计划对特定集合来说很糟糕,因此使用不同的计划。
尝试一个可能有帮助的类比...也许...
假设您有一个周末购物的存储过程。 您通常需要购买杂货,有时需要购买空气过滤器,甚至更不用说一大包每年需要更换 4 次的东西。
- 杂货店可以处理杂货,离你家最近(5分钟)。
- Target 可以处理空气过滤器 和 杂货,但增加 25 分钟的旅行时间。
- "Big place of everything" 拥有您可能需要的一切,但需要一个小时的车程。
所以在这里,根据您的参数 @needsAirFilter
和 @needsBigPackOfSomething
可能会极大地改变 "execution plan" 的 "shopping".
如果 @needsAirFilter
和 @needsBigPackOfSomething
是 false
,则没有理由进行 30 分钟或小时的车程,因为您需要的一切都在杂货店。
一个月一次,@needsAirFilter
是真的,那我们就要去Target了,杂货店的执行计划不够
一年 4 次 @needsBigPackOfSomething
是真的,我们需要花一个小时的时间去买一大包东西,同时还要买杂货和空气过滤器,因为我们在那里。
当然...我们可以每小时开车每个 买杂货的时间,以及其他需要的东西(想象一下单一的执行计划)。但这绝不是最有效的方法。在这种情况下,我们对 information/goods 实际需要的内容有不同的执行计划。
不知道这是否有帮助...但我玩得很开心:D
通常SQL服务器会根据传入的参数值生成一个新的查询计划(这可以确定它将使用哪些索引,如果有的话)以及索引是否被添加、更改或已更新(在 proc 中使用的 tables/views 上)因此 SQL 服务器可能会决定使用一个或多个先前忽略的索引更有效。 SQL 在 proc 中涉及的越多,也会在 SQL 服务器端开始更多的工作,因为它会尝试优化查询。如果数据发生变化(突然间你在新泽西州有更多的客户并且有州的查询和索引)它可能会决定它要使用该索引并且查询计划会改变。如果查询中涉及的任何表或视图更改(架构更改)也将使现有计划无效并导致生成新计划。