<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://www2.sqlblog.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Adam Machanic : cursors</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/tags/cursors/default.aspx</link><description>Tags: cursors</description><dc:language>en</dc:language><generator>CommunityServer 2.1 SP2 (Build: 61129.1)</generator><item><title>"Cursors Run Just Fine"</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2007/10/13/cursors-run-just-fine.aspx</link><pubDate>Sat, 13 Oct 2007 13:42:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:2949</guid><dc:creator>Adam Machanic</dc:creator><slash:comments>14</slash:comments><comments>http://www2.sqlblog.com/blogs/adam_machanic/comments/2949.aspx</comments><wfw:commentRss>http://www2.sqlblog.com/blogs/adam_machanic/commentrss.aspx?PostID=2949</wfw:commentRss><description>&lt;p&gt;I found Linchi's recent post on &lt;a href="http://sqlblog.com/blogs/linchi_shea/archive/2007/10/09/t-sql-cursors-the-case-of-the-published-tpc-e-tests.aspx"&gt;use of cursors in the TPC-E test&lt;/a&gt; to be quite interesting. The question is, why are cursors used in the test when the commonly accepted notion within the SQL Server community is that cursors are a bad thing?&lt;/p&gt;&lt;p&gt;I've posted in the past about situations where cursors were actually &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2006/07/12/running-sums-redux.aspx"&gt;faster than set-based queries&lt;/a&gt;. But in this case I just don't see it; cursoring over an input set to do an update? There's no way that's going to be faster.&lt;/p&gt;&lt;p&gt;&lt;a href="http://blogs.sqlserver.org.au/blogs/greg_linwood/default.aspx"&gt;Greg Linwood&lt;/a&gt; commented in Linchi's post that "indexed cursors run just fine for most purposes". And although I have loads of respect for Greg and his opinions, I just can't agree in this case.&amp;nbsp; I did a few tests on my end just to make sure, and indexed or not, even for the simplest of of queries, cursors perform at least a few times more slowly than their set-based equivalents.&amp;nbsp; Greg mentioned in this comment that the SQL Server engine executes even set-based queries "internally using cursor style processing", but a loop in the query processor's code is clearly not the same as a T-SQL cursor. &lt;/p&gt;&lt;p&gt;The query processor is optimized internally to process data without having to pass it around to different spots in memory or switch context, whereas with a cursor the data is transferred into local variables and your code has to constantly ask the query processor to go back and get some more. This is extremely expensive, which is why even in my experiments with situations where you can see superior performance with cursors, I found that a SQLCLR cursor--which doesn't have to do nearly as much work as a T-SQL cursor--is &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2006/07/12/running-sums-yet-again-sqlclr-saves-the-day.aspx"&gt;vastly superior&lt;/a&gt;.&lt;br&gt;&lt;/p&gt;&lt;p&gt;I'll close with a simple example.&amp;nbsp; The following two batches each run in AdventureWorks, and indexes are irrelevant in both cases.&amp;nbsp; See for yourself which is faster.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;--Set-based&lt;br&gt;SELECT SUM(Quantity)&lt;br&gt;FROM Production.TransactionHistory&lt;br&gt;GO&lt;br&gt;&lt;br&gt;&lt;br&gt;--Cursor-based&lt;br&gt;DECLARE @q INT&lt;br&gt;INT @t INT&lt;br&gt;SET @t = 0&lt;br&gt;&lt;br&gt;DECLARE c CURSOR &lt;br&gt;LOCAL FAST_FORWARD&lt;br&gt;FOR&lt;br&gt;SELECT Quantity &lt;br&gt;FROM Production.Transactionhistory&lt;br&gt;&lt;br&gt;OPEN c&lt;br&gt;&lt;br&gt;FETCH NEXT FROM c INTO @q&lt;br&gt;&lt;br&gt;WHILE @@FETCH_STATUS = 0&lt;br&gt;BEGIN&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SET @t = @t + @q&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; FETCH NEXT FROM c INTO @q&lt;br&gt;END&lt;br&gt;&lt;br&gt;CLOSE c&lt;br&gt;DEALLOCATE c&lt;br&gt;&lt;br&gt;SELECT @t&lt;br&gt;GO &lt;br&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;img src="http://www2.sqlblog.com/aggbug.aspx?PostID=2949" width="1" height="1"&gt;</description><category domain="http://www2.sqlblog.com/blogs/adam_machanic/archive/tags/cursors/default.aspx">cursors</category><category domain="http://www2.sqlblog.com/blogs/adam_machanic/archive/tags/Performance/default.aspx">Performance</category></item></channel></rss>