添加SQL Server索引,但如何仅重新编译受影响的存储过程?

添加SQL Server索引,但如何仅重新编译受影响的存储过程?,sql,sql-server,sql-server-2005,tsql,indexing,Sql,Sql Server,Sql Server 2005,Tsql,Indexing,我需要向一个表添加一个索引,我只想重新编译/编译引用该表的所有存储过程。有没有捷径 编辑: 从SQL Server 2005联机丛书中,重新编译存储过程: 当数据库通过添加索引或更改索引列中的数据等操作进行更改时,用于访问其表的原始查询计划应该通过重新编译来再次优化。此优化在Microsoft SQL Server 2005重新启动后首次运行存储过程时自动进行。如果存储过程使用的基础表发生更改,也会发生这种情况但是,如果添加了一个新索引,存储过程可能从中受益,则只有在Microsoft SQL

我需要向一个表添加一个索引,我只想重新编译/编译引用该表的所有存储过程。有没有捷径

编辑:

从SQL Server 2005联机丛书中,重新编译存储过程:

当数据库通过添加索引或更改索引列中的数据等操作进行更改时,用于访问其表的原始查询计划应该通过重新编译来再次优化。此优化在Microsoft SQL Server 2005重新启动后首次运行存储过程时自动进行。如果存储过程使用的基础表发生更改,也会发生这种情况但是,如果添加了一个新索引,存储过程可能从中受益,则只有在Microsoft SQL Server重新启动后下次运行存储过程时才会进行优化。在这种情况下,强制存储过程在下次执行时重新编译可能会很有用


强制存储过程重新编译的另一个原因是在必要时抵制存储过程编译的“参数嗅探”行为。SQL Server执行存储过程时,该过程在编译时使用的任何参数值都将作为生成查询计划的一部分包含在内。如果这些值表示随后调用过程的典型值,则存储过程在每次编译和执行时都会受益于查询计划。否则,性能可能会受到影响

它们通常会自动重新编译。我想我不知道这是否可以保证,但这是我观察到的-如果您更改(例如添加索引)存储过程引用的对象,那么它将重新编译

create table mytable (i int identity)
insert mytable default values
go 100
create proc sp1 as select * from mytable where i = 17
go
exec sp1
如果查看此执行的计划,它将显示预期的表扫描

create index mytablei on mytable(i)
exec sp1
计划已改为索引搜索

编辑:好的,我提出了一个似乎有效的查询-这将为您提供所有存储过程名称,这些名称引用了计划缓存中的给定表。您可以将存储过程名称与sp_recompile语法连接起来,以生成一组sp_recompile语句,然后执行这些语句

;WITH XMLNAMESPACES (default 'http://schemas.microsoft.com/sqlserver/2004/07/showplan')
,TableRefs (SProcName, ReferencedTableName) as
(
    select
        object_name(qp.objectid) as SProcName,
        objNodes.objNode.value('@Database', 'sysname') + '.' + objNodes.objNode.value('@Schema', 'sysname') + '.' + objNodes.objNode.value('@Table', 'sysname') as ReferencedTableName 
    from sys.dm_exec_cached_plans cp
    outer apply sys.dm_exec_sql_text(cp.plan_handle) st
    outer apply sys.dm_exec_query_plan(cp.plan_handle) as qp
    outer apply qp.query_plan.nodes('//Object[@Table]') as objNodes(objNode)
    where cp.cacheobjtype = 'Compiled Plan'
    and cp.objtype = 'Proc'
)
select 
    * 
from TableRefs
where SProcName is not null
    and isnull(ReferencedTableName,'') = '[db].[schema].[table]'

我相信,如果启用了auto generate statistics(自动生成统计信息)选项,将自动生成一个新的查询计划,这些存储过程可能会从有问题的索引的存在中受益

有关导致自动重新编译的可能性的详细信息,请参阅标题为“重新编译执行计划”的部分


您可以执行sp_重新编译并提供刚刚索引的表名。依赖于该表的所有进程都将从存储的进程缓存中刷新,并在下次执行时进行“编译”

请参见msdn文档:

你说的“重新编译”是什么意思?存储过程不需要编译。您是指更新SQL查询以使用不同的WHERE子句来使用现在已编制索引的列吗?@KG:存储过程需要由SQL Server自动或手动重新编译,以便新的执行计划可以替换计划缓存中现在过期的计划,以便使用新添加的索引。@KG,我认为sp_recompile[@objname=]'object'会导致存储过程和触发器在下次运行时重新编译。添加了一个查询以在计划缓存中查找引用。计划缓存上的Xquery有时非常方便:)这比我的大计划缓存查询更不酷、更实用:)谢谢你的指针。