Does executing a ALTER PROCEDURE
statement for a stored procedure cause all cached execution plans for that stored procedure to become invalid and expire in SQL Server 2008 / 2005?

- 16,471
- 11
- 61
- 86
3 Answers
Yes.
You can verify this by doing
SELECT * FROM sys.dm_exec_procedure_stats
where object_id = object_id('YourProc', 'P')
before and after.
From TechNet
[situations in which plans would be removed from cache include] global operations like running
DBCC FREEPROCCACHE
to clear all plans from cache, as well as changes to a single procedure, such asALTER PROCEDURE
, which would drop all plans for that procedure from cache.

- 84,773
- 49
- 224
- 367

- 438,706
- 87
- 741
- 845
-
Whilst I do believe you (as you have a great reputation) is this documented on MSDN anywhere – Kane Sep 06 '11 at 13:25
-
Yes it will be. Will find a link. – Martin Smith Sep 06 '11 at 13:26
-
@Aaron - Doesn't explicitly mention `ALTER PROC` that I can see. – Martin Smith Sep 06 '11 at 13:31
-
I think the `TABLE` or `VIEW` line is intended to mean any schema change. You can verify with the trace events that the schema changed subclass is what occurs. – Aaron Bertrand Sep 06 '11 at 13:32
-
Well, at least you will see SP:CacheRemove events (not necessarily an explicit recompile). – Aaron Bertrand Sep 06 '11 at 13:38
-
@Aaron - Yep. I was just hoping to find an absolutely unambiguous quote but no luck so far [even in this white paper](http://msdn.microsoft.com/en-us/library/ee343986%28v=sql.100%29.aspx) – Martin Smith Sep 06 '11 at 13:39
-
@Kane - [Found it absolutely unambiguously stated here!](http://technet.microsoft.com/en-us/library/cc293624.aspx) `... These situations included global operations like running DBCC FREEPROCCACHE to clear all plans from cache, as well as changes to a single procedure, such as ALTER PROCEDURE, which would drop all plans for that procedure from cache. ...` – Martin Smith Sep 06 '11 at 14:00
-
1FYI I filed a bug against the documentation. http://connect.microsoft.com/SQLServer/feedback/details/687418/ ... feel free to vote/comment. – Aaron Bertrand Sep 06 '11 at 21:54
-
1The Connect item has been updated with a commitment to correct the documentation. – Aaron Bertrand Apr 24 '12 at 23:47
-
@AaronBertrand, but what about stored procedures which use dynamic SQL where chucks of SQL code are added to (or removed from) the resulting SQL statement? Depending on input parameters same sproc may generate different ad-hoc SQL statements. This can be the case with sprocs used for searching and filtering data to be displayed in UI grids. When such sproc is dropped and created again (e.g. with updated code), are those previously cached plans for every individual sproc calling case also removed from cache? I don't think so. – andrews Sep 25 '18 at 08:04
-
@andrews That is easy to test, right? Remember that something a procedure calls via `sys.sp_executesql` does not "belong" to that stored procedure; the question wasn't about dynamic SQL. If you drop/create or alter the procedure, you'll see the `proc` plan disappear, but any `adhoc` or `prepared` plans that resulted from dynamic SQL will remain, since they are not directly associated with the procedure (and can be shared with other procedures, or ad hoc code, that calls the exact same statements with the exact same session settings). – Aaron Bertrand Sep 25 '18 at 15:03
Yes. Of course this is easy to test yourself:
- Create a procedure
- Execute it a few times
- Confirm it is cached by checking sys.dm_exec_cached_plans
- Alter the procedure
The row in sys.dm_exec_cached_plans is gone
CREATE PROCEDURE dbo.blat AS SELECT 1; GO EXEC dbo.blat; GO 5 SELECT COUNT(*) FROM sys.dm_exec_cached_plans AS p CROSS APPLY sys.dm_exec_sql_text(p.plan_handle) AS s WHERE [sql].[text] LIKE '%dbo.blat%'; ----- 1 ALTER PROCEDURE dbo.blat AS SELECT 22; GO SELECT COUNT(*) FROM sys.dm_exec_cached_plans AS p CROSS APPLY sys.dm_exec_sql_text(p.plan_handle) AS s WHERE [sql].[text] LIKE '%dbo.blat%'; ----- 0
But if your procedure has dynamic SQL, the main Proc
plan will disappear, but child plans (Adhoc
/ Prepared
) will remain.
CREATE PROCEDURE dbo.what
AS
BEGIN
DECLARE @sql nvarchar(max) = N'SELECT x FROM dbo.flange;';
EXEC sys.sp_executesql @sql;
END
GO
DBCC FREEPROCCACHE;
GO
EXEC dbo.what;
GO
SELECT objtype, c = COUNT(*)
FROM sys.db_exec_cached_plans AS p
CROSS APPLY sys.dm_exec_sql_text(p.plan_handle) AS t
WHERE t.text LIKE N'%flange%'
GROUP BY objtype;
GO
Results:
objtype c
------- ----
Adhoc 1
Proc 1
Now, alter the procedure (but in such a way that it still produces the same SQL):
ALTER PROCEDURE dbo.what
AS
BEGIN
SET NOCOUNT ON;
DECLARE @sql nvarchar(max) = N'SELECT id FROM dbo.flange2;';
EXEC sys.sp_executesql @sql;
END
GO
The query above yields:
objtype c
------- ----
Adhoc 1
Of course this is not a permanent state - other queries and other memory pressure on the system will dictate how long those ad hoc queries stay in the cache.

- 272,866
- 37
- 466
- 490
It does - but there may be other factors.
Sometimes with severe performance problems, I've found that explicitly running DBCC FREEPROCCACHE
can vastly improve performance of the system. Of course you can also explicitly clear the cache for a single sproc if you know it's having problems.

- 19,064
- 3
- 47
- 70
-
Is this in a situation where the plan cache is full of a lot of single use adhoc queries or something? If so optimise for adhoc workloads could be an option. – Martin Smith Sep 06 '11 at 13:55
-
To be honest I've seen this a few times, spent a lot of time on it the first time trying to resolve - had contractors in and everything. We never got to the route cause only discovered that after a lot of database updates sometimes it was necessary to call `DBCC FREEPROCCACHE`. – TheCodeKing Sep 06 '11 at 13:58