Performance improvement of cursor SQL Server Cursor-Loca-Fast-Forward

Performance improvement of cursor SQL Server

Hey folks till now we have discussed User defined functions in sqlKill Processes in sql server 2008, View in sql default constraint in sql , Remove Cross duplicate rows in SQLRecursive SQL Query , Recursive SQL Query-2STUFF and CONCAT in SQLRANK in SQL server , Difference between temporary table and table variable in sql serverUNIQUEIDENTIFIER in SQL ServerRAW Mode with FOR XML , AUTO Mode with FOR XMLEXPLICIT Mode with FOR XML , PATH Mode with FOR XMLOUTPUT Clause in SQL ServerDifference between delete and truncate in sql server etc.

Today we will discuss regarding Performance improvement of cursor SQL Server

Sample example of Cursor without any optimization

 

Lets start with simple example of cursor and try to run that example & measure execution time.

	
USE tempdb;
GO

IF OBJECT_ID(N'dbo.technothirsty',N'U') IS NOT NULL
BEGIN
DROP TABLE dbo.technothirsty;
END

SELECT s1.name INTO dbo.technothirsty FROM sys.all_columns AS s1
CROSS JOIN (SELECT n FROM (VALUES(1),(2),(3),(4)) AS s(n)) as n1
CROSS JOIN (SELECT n FROM (VALUES(1),(2),(3),(4)) AS s(n)) as n2
CROSS JOIN (SELECT n FROM (VALUES(1),(2),(3),(4)) AS s(n)) as n3
CROSS JOIN (SELECT n FROM (VALUES(1),(2),(3),(4)) AS s(n)) as n4

CREATE CLUSTERED INDEX x ON dbo.technothirsty(name);
GO

DECLARE @name SYSNAME, @i INT=0;

DECLARE c CURSOR
FOR SELECT name FROM dbo.technothirsty;

OPEN c;

FETCH c INTO @name;

WHILE @@FETCH_STATUS=0
BEGIN
SET @i+=1;
FETCH c INTO @name;
END

CLOSE c;
DEALLOCATE c

 

We have run above query in sql server and measured execution time, it took 47 seconds to execute which is as below:

 

Cursor

 

Apply FAST_FORWARD to optimize query

 

	
USE tempdb;
GO

IF OBJECT_ID(N'dbo.technothirsty',N'U') IS NOT NULL
BEGIN
DROP TABLE dbo.technothirsty;
END

SELECT s1.name INTO dbo.technothirsty FROM sys.all_columns AS s1
CROSS JOIN (SELECT n FROM (VALUES(1),(2),(3),(4)) AS s(n)) as n1
CROSS JOIN (SELECT n FROM (VALUES(1),(2),(3),(4)) AS s(n)) as n2
CROSS JOIN (SELECT n FROM (VALUES(1),(2),(3),(4)) AS s(n)) as n3
CROSS JOIN (SELECT n FROM (VALUES(1),(2),(3),(4)) AS s(n)) as n4

CREATE CLUSTERED INDEX x ON dbo.technothirsty(name);
GO

DECLARE @name SYSNAME, @i INT=0;

DECLARE c CURSOR FAST_FORWARD
FOR SELECT name FROM dbo.technothirsty;

OPEN c;

FETCH c INTO @name;

WHILE @@FETCH_STATUS=0
BEGIN
SET @i+=1;
FETCH c INTO @name;
END

CLOSE c;
DEALLOCATE c

 

We have added FAST_FORWARD at the end of declaration of Cursor, now we got execution time 26 seconds as below:

 

Cursor-Fast-Forward

FAST_FORWARD will give order to go forward only while cursor traverse through loop.

 

Apply LOCAL FAST_FORWARD to further optimization

 

	
USE tempdb;
GO

IF OBJECT_ID(N'dbo.technothirsty',N'U') IS NOT NULL
BEGIN
DROP TABLE dbo.technothirsty;
END

SELECT s1.name INTO dbo.technothirsty FROM sys.all_columns AS s1
CROSS JOIN (SELECT n FROM (VALUES(1),(2),(3),(4)) AS s(n)) as n1
CROSS JOIN (SELECT n FROM (VALUES(1),(2),(3),(4)) AS s(n)) as n2
CROSS JOIN (SELECT n FROM (VALUES(1),(2),(3),(4)) AS s(n)) as n3
CROSS JOIN (SELECT n FROM (VALUES(1),(2),(3),(4)) AS s(n)) as n4

CREATE CLUSTERED INDEX x ON dbo.technothirsty(name);
GO

DECLARE @name SYSNAME, @i INT=0;

DECLARE c CURSOR LOCAL FAST_FORWARD
FOR SELECT name FROM dbo.technothirsty;

OPEN c;

FETCH c INTO @name;

WHILE @@FETCH_STATUS=0
BEGIN
SET @i+=1;
FETCH c INTO @name;
END

CLOSE c;
DEALLOCATE c

LOCAL keyword is used to make cursor local, by default cursor is Global, so cursor generally taking more time to execute.

As you have noticed that I have added LOCAL and FAST_FORWARD in cursor query. Lets run this query in sql server, I got execution time 25 seconds as below:

 

Performance improvement of cursor SQL Server Cursor-Loca-Fast-Forward Here are the techniques by which we can optimize execution time of cursor query.

Friends let me know if you have any better ideas to optimize.

Leave a Reply