articledblogs.com articledblogs.com articledblogs.com
Search:    Site Home >> About Us >> Privacy >> Terms & Conditions >> Place Your Link >> Submit Article   
Add Url
 

Recreation & Entertainment

Academics & Learning

Hotels & Travel

Healthcare & Treatment

Outdoor & Sports

Relationship & Lifestyle

Computers & Networking

Companies & Business

Automobile & Automotive

Events & News

Shopping Online

Property & Estate

Policies & Law

Online & Indoor Games

Science & Space

Art & Creative

Society & Issues

Family & Home

Employment & Careers

Banking & Finance

Self Healing

Eating & Drinking

Children & Teens

Health & Hygiene

 

Site Home » Automobile & Automotive » Software Solutions
 

Eliminating cursor in SQL Server

 
We all know how cursors are slow and how badly they tend to issue a lock on part of the table, or on the whole table, during its execution. To explain exactly what is going on, and what we can do to optimize the performance, here is an example:

Table t_Customers has 3000 records.

Table t_Orders has 1 to 100 records for each record in t_Customers table, making it a table with 65000 records.

We want to print all of the orders for customers that had orders in the last month. There are several solutions that we can use and first one is usage of the cursor:

Declare
@nCustID Int
, @cCustName varchar(30)
, @nOrdNo Int

Declare curCusOrd For
Select
C.CustID
, C.CustName
, O.OrderNo
From
t_Customers C
Left Join t_Orders O
On C.CustID = O.CustID
Where
O.OrderDate >= DateAdd( month, -1, GetDate() )

Fetch Next From curCusOrd
Into
@nCustID
, @cCustName
, @nOrdNo

While @@Fetch_Status = 0
Begin

/*
Print Order
*/

Fetch Next From curCusOrd
Into
@nCustID
, @cCustName
, @nOrdNo

End

Close curCusOrd
DeAllocate curCusOrd

In example above, cursor will lock part of each table, or both tables as a whole, while orders are printed. On top of this, a lot of disk activities will be done in order to scan both t_Customers and t_Orderd tables, resulting a very slow performance.

The first alternative is to create a temporary table, that will contain all key columns, and then to use it as a pointer instead of cursor. For a small dataset we can easily eliminate a slow performing and memory intense cursor with a temporary table. Here is a same procedure done with temporary table:

Declare
@nCustID Int
, @cCustName varchar(30)
, @nOrdNo Int
, @nRowCnt Int
, @nRows Int

Create Table #tempCustOrd
(
CusOrdID IDENTITY (1, 1) Primary key Not Null
, CustID Int Not Null
, CustName varchar(30) Not Null
, OrderNo Int
)

Insert #tempCustOrd
Select
C.CustID
, C.CustName
, O.OrderNo
From
t_Customers C
Left Join t_Orders O
On C.CustID = O.CustID
Where
O.OrderDate >= DateAdd( month, -1, GetDate() )

Select
@ nRowCnt = 1
, @nRows = Count(*)
From #tempCustOrd

While @nRowCnt <= @nRows
Begin

Select
C.CustID
, C.CustName
, O.OrderNo
From #tempCustOrd
Where CusOrdID = @nRowCnt

/*
Print Order
*/

Select @nRowCnt = @nRowCnt + 1

End

Drop Table #tempCustOrd

Locks that were issued on t_Customers and t_Orders are now eliminated, but the price is a lot of disk activities, along with the potential locking of whole temporary table. All of this adds up to a lousy performance, especially on large or long-running operations.

The third alternative is to use a SQL Server Table variable. This is a variable that can be used in stored procedures, functions and batches. They have no permanent life outside of the batch that contains them. They're cleaned up automatically at the end of the batch and you don't need to worry about name conflicts with anything outside of this scope. Within its scope, a table variable behaves like a permanent table.

Now lets take a look at our example using a Table variable. It is almost identical as the temporary table example. Only difference is the table declaration and the fact that you do not need to drop it after you're done using it. So here is our code with Table variable:

Declare
@nCustID Int
, @cCustName varchar(30)
, @nOrdNo Int
, @nRowCnt Int
, @nRows Int

Declare @t_CustOrd Table
(
CusOrdID IDENTITY (1, 1) Primary key Not Null
, CustID Int Not Null
, CustName varchar(30) Not Null
, OrderNo Int
)

Insert @t_CustOrd
Select
C.CustID
, C.CustName
, O.OrderNo
From
t_Customers C
Left Join t_Orders O
On C.CustID = O.CustID
Where
O.OrderDate >= DateAdd( month, -1, GetDate() )

Select
@ nRowCnt = 1
, @nRows = Count(*)
From @t_CustOrd

While @nRowCnt <= @nRows
Begin

Select
C.CustID
, C.CustName
, O.OrderNo
From @t_CustOrd
Where CusOrdID = @nRowCnt

/*
Print Order
*/

Select @nRowCnt = @nRowCnt + 1

End

Table variable resides in memory, there is no disk I/O, it does not use tempdb, therefore eliminating all of the locks. Execution is fast; it takes 1/5 of time to complete the same job then it would using cursors.

As you can expect there are limitations:
- Server physical memory. Always keep your server memory in mind when you work with Table variable
- You can not create index on the Table variable. If you need to work with a large amount of data with many indexes, use a temporary table instead of a table variable
- The table scheme on Table variable is static. If you need to modify it in the course of a batch, use a temporary table instead.
- You can not use Select Into statement on a Table variable

As a general rule of thumb, you should use table variable any time that your temporary data is of reasonable size and is only used a few times. As your temporary data grows in size, complexity, and reuse, a temporary table will be more appropriate. Using execution plans, SQL Profiler, and performance counters available to monitor what's going on inside of your stored procedures, you can code the alternatives and test them when there's any doubt.

Author: Marin Kostadinovic
 
Author Bio:

Marin Kostadinovic is in the database development/architecture and website design business for more than 20 years. He is currently mastering www.website-hosting-development.com?? >Website Hosting and Development and www.dimm-is.com >DIMM Info Systems Inc. websites.

 
 
 

Related Articles

 
Using the Web Accessibility Toolbar
 
Land Rover LR2, Back On The Streets
 
Plug-In Hybrid Vehicles - The Next Step In Hybrid Evolution
 
Gift Flower Screensavers
 
Get Cheap Car Insurance For Your Teenager - Three Tips To Save Money
 
Much-Awaited Nissan And Ford Pairing
 
Getting an Online insurance quote
 
The Race Car Inspired BMW M3
 
Buy To Let Property Insurance
 
What's The Difference Between Whole And Term Life Insurance?
 
 
 
 
 

Backup Software- Don??t Buy It!

Backup Software is for the birds! Computer Backup is too hard, too much trouble and a pain in the bu ... - Jack Back
 

Battling an Unfair Health Insurance Claim Can Really Pay Off

Are you having trouble getting your insurance company to pay your medical health costs? Join the clu ... - L. H. Findlay
 

How To Find Very Cheap Car Insurance

No one wants to pay for more than what theyre actually getting, and no one wants to pay for services ... - Jessica Farrell
 
 

100% Free Article Distribution Software Available to Authors

I have in my possession a link to a very rare free article distributor program. For about 6 months t ... - David F.
 

Chrysler 300C SRT8: The Fusion of Luxury and Performance

The Chrysler 300C put the excitement back into full sized rear wheel drive American cars like no oth ... - Matthew C. Keegan
 
 
   Site Home >> Privacy >> Terms & Conditions
Copyright © 2008 www.articledblogs.com