Professional Documents
Culture Documents
Home
Back
Articles
Books
Q&A
Book Excerpts
Careers
Products
*****
Design your application to allow your users to cancel running queries. Not doing so may
force the user to reboot the client, which can cause unresolvable performance problems. [6.5,
7.0, 2000]
*****
Many stored procedures have the option to accept multiple parameters. This in and of itself is not
a bad thing. But what can often cause problems is if the parameters are optional, and the
number of parameters varies greatly each time the stored procedure runs. There are two
ways to handle this problem, the slow performance way and fast performance way.
If you want to save your development time, but don't care about your application's performance,
you can write your stored procedure generically so that it doesn't care how many parameters it
gets. The problem with this method is that you may end up unnecessarily joining tables that
don't need to be joined based on the parameters submitted for any single execution of the stored
procedure.
Another, much better performing way, although it will take you more time to code, is to include
IF...ELSE logic in your stored procedure, and create separate queries for each possible
combination of parameters that are to be submitted to the stored procedure. This way, you can
be sure you query is as efficient as possible each time it runs. [6.5, 7.0, 2000] Added 12-292000
*****
Here's another way to handle the problem of not knowing what parameters your stored
procedure might face. In fact, it will probably perform faster than the tip listed above.
Although the above tip is a good starting point, it's not complete. The problem is the query-plans,
the pre-compilation of stored procedures, that SQL Server does for you. As you know, one of the
biggest reasons to use stored procedures instead of ad-hoc queries is the performance gained by
using them. The problem that arises with the above tip is that SQL Server will only generate a
query-plan for the path taken through your stored procedure when you first call it, not all
possible paths.
Let me illustrate this with an example. Consider the following procedure (pre-compilation doesn't
really have a huge effect on the queries used here, but these are just for illustration purposes):
CREATE PROCEDURE dbo.spTest (@query bit) AS
IF @query = 0
SELECT * FROM authors
ELSE
SELECT * FROM publishers
GO
Suppose I make my first call to this procedure with the @query parameter set to 0. The queryplan that SQL Server will generate will be optimized for the first query ("SELECT * FROM
authors"), because the path followed on the first call will result in that query being executed.
Now, if I next call the stored procedure with @query set to 1, the query plan that SQL Server has
in memory will not be of any use in executing the second query, since the query-plan is
optimized for the authors table, not the publishers table. Result: SQL Server will have to compile
a new query plan, the one needed for the second query. If I next call the procedure with @query
set to 0 again, the whole path will have to be followed from the start again, since only one queryplan will be kept in memory for each stored procedure. This will result in sub-optimal
performance.
As it happens I have a solution, one that I've used a lot with success. It involves the creation of
what I like to call a 'delegator'. Consider again spTest. I propose to rewrite it like this:
CREATE PROCEDURE dbo.spTestDelegator (@query bit) AS
IF @query = 0
EXEC spTestFromAuthors
ELSE
EXEC spTestFromPublishers
GO
CREATE PROCEDURE dbo.spTestFromAuthors AS
file:///E|/k/SQL%20Server%20Database%20Store...0Procedure%20Performance%20Tuning%20Tips.htm (2 of 6) [13/11/2002 1:04:35]
instead, it must re-execute the stored procedure, which hinders performance. [7.0, 2000] Added
10-12-2000
*****
When you need to execute a string of Transact-SQL, you should use the sp_executesql
stored procedure instead of the EXECUTE statement. Sp_executesql offers to major
advantages over EXECUTE. First, it supports parameter substitution, which gives your more
options when creating your code. Second, it creates query execution plans that are more likely to
be reused by SQL Server, which in turn reduces overhead on the server, boosting performance.
Sp_executesql executes a string of Transact-SQL in its own self-contained batch. When it is run,
SQL Server compiles the code in the string into an execution plan that is separate from the batch
that contained the sp_executesql and its string.
Learn more about how to use sp_executesql in the SQL Server Books Online. [7.0, 2000] Added
3-7-2001
*****
SQL Server will automatically recompile a stored procedure if any of the following happens:
If you run sp_recompile for any table referenced by the stored procedure.
If any schema changes occur to any of the objects referenced in the stored procedure. This
includes adding or dropping rules, defaults, and constraints.
New distribution statistics are generated.
If you restore a database that includes the stored procedure or any of the objects it
references.
as you don't want a stored procedure to be running an outdated query plan. But again,
sometimes stored procedures recompile more than they have to. Here are some suggestions on
how to reduce some of the unnecessary recompilations:
Unnecessary Stored Procedure Recompilations Due to Mixing DDL and DML Statements in the
Same Stored Procedure
If you have a DDL (Data Definition Language) statement in your stored procedure, the stored
procedure will automatically recompile when it runs across a DML (Data Manipulation Language)
statement for the first time. And if you intermix both DDL and DML many times in your stored
procedure, this will force a recompilation every time it happens, hurting performance.
To prevent unnecessary stored procedure recompilations, you should include all of your DDL
statements at the first of the stored procedure so they are not intermingled with DML statements.
Unnecessary Stored Procedure Recompilations Due to Specific Temporary Table Operations
Improper use of temporary tables in a stored procedure can force them to be recompiled every
time the stored procedure is run. Here's how to prevent this from happening:
Any references to temporary tables in your stored procedure should only refer to tables
created by that stored procedure, not to temporary tables created outside your stored
procedure, or in a string executed using either the sp_executesql or the EXECUTE
statement.
All of the statements in your stored procedure that include the name of a temporary table
should appear syntactically after the temporary table.
The stored procedure should not declare any cursors that refer to a temporary table.
Any statements in a stored procedure that refer to a temporary table should precede any
DROP TABLE statement found in the stored procedure.
The stored procedure should not create temporary tables inside a control-of-flow
statement.
connections, which means that stored procedures can be reused more often. If you write an
application where every user opens their own connection, then stored procedures cannot be
reused as often, reducing performance. [7.0, 2000] Added 10-12-2000
*****
Avoid nesting stored procedures, although it is perfectly legal to do so. Nesting not only
makes debugging more difficult, it makes it much more difficult to identify and resolve
performance-related problems. [6.5, 7.0, 2000] Added 10-12-2000
*****
If you use input parameters in your stored procedures, you should validate all of them
at the beginning of your stored procedure. This way, if there is a validation problem and the
client applications needs to be notified of the problem, it happens before any stored procedure
processing takes place, preventing wasted effort and boosting performance. [6.5, 7.0, 2000]
Added 10-12-2000
*****
When calling a stored procedure from your application, it is important that you call it
using its fully qualified name. Such as:
exec database_name.dbo.myProcedure
instead of:
exec myProcedure
Why? There are a couple of reasons, one of which relates to performance. First, using fully
qualified names helps to eliminate any potential confusion about which stored procedure you
want to run, helping to prevent bugs and other potential problems. But more importantly, doing
so allows SQL Server to access the stored procedures execution plan more directly, and in turn,
speeding up the performance of the stored procedure. Yes, the performance boost is very small,
but if your server is running tens of thousands or more stored procedures every hour, these little
time savings can add up. [7.0, 2000] Added 3-7-2001 More from Microsoft
*****
If a stored procedure needs to return only a single value, and not a recordset, consider
returning the single value as an output statement. While output statements are generally
used for error-checking, they can actually be used for any reason you like. Returning a single
value as at output statement is faster than returning a single value as part of a recordset. [6.5,
7.0, 2000] Added 8-1-2001