Frequently we use the Stored Procedure in our application to perform data manipulation and data query or both. In that case Performance is most importance because best performance is the main concern to develop a successful application. In this post I want to point out what are the things we need to follow to write best stored procedure with performance.
-
SET NOCOUNT
When we executing the select or DML (Insert, Update, and Delete) query in SQL server it return the message that inform to how many row that query affect in database. This information is useful for debugging purpose but definitely it take some time to write that message. It will affect the performance.To avoid it we have to Include SET NOCOUNT ON In above the query. For example
CREATE PROC
dbo.ProcName
AS
BEGIN
SET
NOCOUNTON;
--Procedure code here
SELECT column1 FROM dbo.TblTable1
-- Reset SET NOCOUNT to OFF
SET
NOCOUNTOFF;
GO
END
-
Create Clustered and Non-Clustered Indexes
Practice to create clustered and non clustered index since indexes helps in to access data fastly. But be careful, more indexes on a tables will slow the INSERT,UPDATE,DELETE operations. Hence try to keep small no of indexes on a table.
-
Use schema name with object name
Schema name should be used with all the object we used in stored procedure. Because if we use the object without schema name, in executing time it search all the schema one by one to find the object. So better use Schema with object. For example.
CREATE PROC
dbo.ProcName
AS
BEGIN
SET
NOCOUNTON;
--Preferred way querying table
SELECT
column1FROM
dbo.TblTable1
– Should avoid
SELECT
column1FROM
TblTable1
--Preferred way to call sp
EXEC
dbo.MyProce
– Should avoid
EXEC
MyProce
-- Reset SET NOCOUNT to OFF
SET
NOCOUNTOFF;
GO
END
-
Do not use the prefix “sp_” in the stored procedure name
If a stored procedure name begins with “SP_,” then SQL server first searches in the master database and then in the current session database. Searching in the master database causes extra overhead and even a wrong result if another stored procedure with the same name is found in master database.
-
Use IF EXISTS (SELECT 1) instead of (SELECT *)
Sometimes we need to check the records is already present in table or not for that we use IF EXISTS. For example if the records already exist in table then update otherwise insert. In that case we use IF EXISTS class it return “true” if any records is return by internal query either single value “1” are all columns.
CREATE PROC
dbo.ProcName
AS
BEGIN
SET
NOCOUNTON
;
--Preferred way querying table
IF
EXISTS(select
1from
BatchWHERE
BatchName ='batch1'
)
BEGIN
Update BatchSet
BoolParam =0WHERE BatchName =
'batch1'
END
ELSE
BEGIN
Insert
Batch(BatchName)values
('batch1'
)
END
---- Reset SET NOCOUNT to OFF
SET
NOCOUNTOFF
;
GO
END
-
Use TRY-Catch for error handling
The stored procedure have more than one T-SQL statement .In that case weed to check after every t-SQl statement is any error have. To avoid that we use TRY-Catch
CREATE PROC
dbo.ProcName
AS
BEGIN
SET
NOCOUNTON
;
BEGIN TRY
Select
1/1
Select
1/0
END TRY
BEGIN CATCH
RAISERROR
('Error raised in TRY block.
', 16, 1);
END CATCH
-- Reset SET NOCOUNT to OFF
SET
NOCOUNTOFF
;
GO
END
-
Use TRY-Catch for error handling
The sp_executesql stored procedure supports parameters. So, using the sp_executesql stored procedure instead of the EXECUTE statement improve the re-usability of your code. The execution plan of a dynamic statement can be reused only if each and every character, including case, space, comments and parameter, is same for two statements. For example, if we execute the below batch
DECLARE
@QueryVARCHAR
(100)
DECLARE
@AgeINT
SET
@Age = 25
SET
@Query ='SELECT * FROM dbo.tblPerson WHERE Age = '
+ convert(VARCHAR
(3),@Age)
EXEC
(@Query)If we again execute the above batch using different @Age value, then the execution plan for SELECT statement created for @Age =25 would not be reused. However, if we write the above batch as given below,DECLARE
@QueryVARCHAR
(100)
DECLARE
@AgeINT
SET
@Age = 25
SET
@Query ='SELECT * FROM dbo.tblPerson WHERE Age = '
+ convert(VARCHAR
(3),@Age)
execute sp_executesql
@QueryN'@Age int'
, @Age = 25the compiled plan of this SELECT statement will be reused for different value of @Age parameter. The reuse of the existing complied plan will result in improved performance -
Choose Appropriate Data Type
Choose appropriate SQL Data Type to store your data since it also helps in to improve the query performance. Example: To store strings use varchar in place of text data type since varchar performs better than text. Use text data type, whenever you required storing of large text data (more than 8000 characters). Up to 8000 characters data you can store in varchar.
-
Avoid nchar and nvarchar
Practice to avoid nchar and nvarchar data type since both the data types takes just double memory as char and varchar. Use nchar and nvarchar when you required to store Unicode (16-bit characters) data like as Hindi, Chinese characters etc.
-
Avoid * in SELECT statement
Practice to avoid * in Select statement since SQL Server converts the * to columns name before query execution. One more thing, instead of querying all columns by using * in select statement, give the name of columns which you required
-- Avoid
SELECT
*FROM
tblName
--Best practice
SELECT
col1,col2,col3FROM
tblName -
CREATE PROCEDURE with WITH RECOMP
The WITH RECOMPILE option prevents reusing the stored procedure execution plan, so SQL Server does not cache a plan for this procedure and the procedure is recompiled at run time. Using the WITH RECOMPILE option can boost performance if your query will vary each time it is run from the stored procedure because in this case the wrong execution plan will not be used.
Great artice, thanks!
ReplyDelete