Reasons that a stored procedure
will recompile
SQL Server 2000 recompiles a stored procedure for
many reasons. The first group of reasons that cause
recompiles are:
- requests to recompile an individual
procedure
- Requests to recompile procedures that depend
on a database object, such as a table or view
- Actions that result in the recompilation of
all procedures.
In explicit SQL Server terms these reasons are:
- Use of the WITH RECOMPILE option on the
CREATE PROC or ALTER PROC statement. The
May 6th issue of my T-SQL UDF of the
Week Newsletter has an article about how to
detect which procedures were created with the
WITH RECOMPILE option and has a user-defined
function that lists all such procedures.
- Executing the system stored procedure
sp_recompile on the
procedure or on a table or view that the
procedure depends on.
- Use of the WITH RECOMPILE option on the EXEC
statement
- Use of DBCC FREEPROCCACHE
These reasons are fairly easy to fix. Next
month's article has a section on how to locate these
easily, and gives some methods for minimizing them
when they are really necessary.
The next group of reasons that recompilation
occurs is because a change has occurred in a
database or database object that invalidates the
cached execution plan. These reasons are:
- Restoring the database containing the
procedure or any of the objects that the
procedure references. Most often, this involves
restoring a database that is referenced by the
stored procedure.
- A schema change in any of the objects that
are referenced by the procedure. This includes
the addition or alteration of a column,
constraint or index on a table or view
referenced by the procedure.
- Statistics Change. These can be
automatically generated by SQL Server or
requested with the CREATE STATISTICS or UPDATE
STATISTICS statements.
Restoring a database usually will not wait. You
will just have to live with any recompiles caused by
restores. Schema changes should be scheduled for off
hours when any recompiles caused have minimal
impact. Statistics changes can happen automatically
if the database option 'auto create statistics' is
on. Automatic update of statistics was a major issue
in version 7 because, when working on temporary
tables, SQL Server would recalculate statistics, and
therefore recreate the plan, after only five
modifications to a temporary table. SQL Server has
an improved algorithm for automatic updating of
statistics. If this is the reason for
recompilations, you may want to consider turning off
the automatic generation of statistics.
Memory constraints cause the next reason:
- The plan being aged out of cache.
If this is occurring frequently, you should
address the overall memory requirements of the SQL
Server instance.
The final two reasons occur in the executing
stored procedure. They are the causes that are most
amenable to better programming:
- Interleaving Data Definition Language (DDL)
and Data Manipulation (DML) operations.
Execution of DDL statements, such as the
creation of permanent or temporary tables and
indexes on tables, forces a recompile at the
next DML statement, such an INSERT, UPDATE, or
SELECT.
- Using one of these SET statements to change
a connection option:
- SET ANSI_DEFAULTS
- SET ANSI_NULLS
- SET ANSI_PADDING
- SET ANSI_WARNINGS
- SET CONCAT_NULL_YIELDS_NULL
Because these two reasons cause most of the
recompiles, I consider the problem pretty fixable.
It is a matter of modifying the logic of your stored
procedure to be more aware of what causes
recompiles. The stored procedure shown next causes
several compiles due to interleaved DDL and DML and
use of SET statements.
SET QUOTED_IDENTIFIER ON
SET ANSI_NULLS ON
GO
CREATE PROCEDURE dbo.usp_Recompiles_SeveralTimes AS
SET NOCOUNT ON -- Doesn't cause a recompile
-- Cause a recompile due to creation of the temporary table
CREATE TABLE #Temp1 ([id] int identity (1,1)
, [name] varchar(64))
INSERT INTO #Temp1 ([name]) VALUES ('Gregor Samsa')
-- Cause a recompile because of a change in a session option
SET ANSI_NULLS OFF
INSERT INTO #Temp1 ([name]) VALUES ('Padme Amidala')
-- Cause a recompile because of a change in a session option
SET ANSI_WARNINGS OFF
INSERT INTO #Temp1 ([name]) VALUES ('Casper Guttman')
-- Cause a recompile because of a new index
CREATE CLUSTERED INDEX IDX_Name ON #Temp1 ([name])
SELECT * FROM #Temp1 ORDER BY [name]
DROP TABLE #Temp1 -- Doesn't Cause a recompile
GO
We will use this stored procedure as an example
for how to monitor and diagnose recompiles in the
next section.