<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>rusanu.com</title>
	<atom:link href="http://rusanu.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://rusanu.com</link>
	<description>RUSANU CONSULTING LLC</description>
	<pubDate>Sat, 21 Aug 2010 17:05:34 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6</generator>
	<language>en</language>
			<item>
		<title>SqlDependency based caching of LINQ Queries</title>
		<link>http://rusanu.com/2010/08/04/sqldependency-based-caching-of-linq-queries/</link>
		<comments>http://rusanu.com/2010/08/04/sqldependency-based-caching-of-linq-queries/#comments</comments>
		<pubDate>Wed, 04 Aug 2010 20:23:37 +0000</pubDate>
		<dc:creator>remus</dc:creator>
		
		<category><![CDATA[Announcements]]></category>

		<category><![CDATA[Tutorials]]></category>

		<category><![CDATA[cache]]></category>

		<category><![CDATA[caching]]></category>

		<category><![CDATA[linq]]></category>

		<category><![CDATA[query notificaitons]]></category>

		<category><![CDATA[sql]]></category>

		<category><![CDATA[sql server]]></category>

		<category><![CDATA[SqlDependency]]></category>

		<guid isPermaLink="false">http://rusanu.com/?p=863</guid>
		<description><![CDATA[Query Notifications is the SQL Server feature that allows a client to subscribe to notifications that are sent when data in the database changes irrelevant of how that change occurs. I have talked before about how Query Notifications works in the article The Mysterious Notification. This feature was designed specifically for client side cache invalidation: [...]]]></description>
			<content:encoded><![CDATA[<p>Query Notifications is the SQL Server feature that allows a client to subscribe to notifications that are sent when data in the database changes <i>irrelevant of how that change occurs</i>. I have talked before about how Query Notifications works in the article <a href="http://rusanu.com/2006/06/17/the-mysterious-notification/">The Mysterious Notification</a>. This feature was designed specifically for client side cache invalidation: the applications runs a query, gets back the result and stores it in the cache. Whenever the result is changed because data was updated, the application will be notified and it can invalidate the cached result.</p>
<p>Leveraging Query Notifications from the managed clients is very easy due to the dedicated SqlDependency class that takes care of a lot of the details needed to be set up in place in order to be able to receive these notifications. But the MSDN examples and the general community know how with SqlDepenendency is geared toward straight forward usage, by attaching it to a SqlCommand object.</p>
<h1>Leveraging SqlDependency from LINQ queries</h1>
<p>There is no clear guidance from MSDN on how to mix these two technologies: Query Notifications and LINQ. There are a few in the community who have given hints on what has to be done, like this article <a href="http://dunnry.com/blog/UsingSQLDependencyObjectsWithLINQ.aspx">Using SQLDependency objects with LINQ</a> by Ryan Dunn (<a href="http://dunnry.com/blog/">blog</a>|<a href="http://twitter.com/dunnry">twitter</a>).</p>
<p>My goal is to propose an easy to use extension method that can add SqlDependency based caching to any IQueryable&lt;T&gt;. Usage should be as simple as:</p>
<p><code></p>
<pre>
var queryTags = from t in ctx.Tags select t;
var tags = queryTags.AsCached("Tags");
foreach (Tag t in tags)
{
  ...
}
</pre>
<p></code></p>
<p>The first invocation should run the query and return the result, setting up a SqlDependency notification and also caching the result. Subsequent invocations should return the cached result, without hitting the database. Any change to the Tags table in my example should trigger the SqlDependency and invalidate the cache. Next invocation would again run the query and return the updated result, setting up a new SqlDependency notification and caching the new result.</p>
<h1>LinqToCache project</h1>
<p>My solution is available as the <a href="http://code.google.com/p/linqtocache/">LinqToCache project</a>. To cache a LINQ query results and get active SqlDependency notifications when the data was changed, simply download the appropriate DLL for your target framework (.Net 3.5 or .Net 4.0) and add it as a reference to your project. Now any LINQ query (any IQueryable) will have a new extension method <tt>AsCached</tt>. This method returns an IEnumerable of the query result. First invocation will always hit the database and set up a SqlDependency, subsequent invocations will return the cached result as long as it was not invalidated.</p>
<h1>Query Notifications restrictions</h1>
<p>Not every query can be subscribed for notifications. The gory details of what works and what doesn&#8217;t are described in MSDN at <a href="http://msdn.microsoft.com/en-us/library/ms181122.aspx" target="_blank">Creating a Query for Notification</a>:</p>
<blockquote>
<ul>
<li>The projected columns in the SELECT statement must be explicitly stated, and table names must be qualified with two-part names. Notice that this means that all tables referenced in the statement must be in the same database.</li>
<li>The statement may not use the asterisk (*) or table_name.* syntax to specify columns.</li>
<li>The statement may not use unnamed columns or duplicate column names.</li>
<li>The statement must reference a base table.</li>
<li>The statement must not reference tables with computed columns.</li>
<li>The projected columns in the SELECT statement may not contain aggregate expressions unless the statement uses a GROUP BY expression. When a GROUP BY expression is provided, the select list may contain the aggregate functions COUNT_BIG() or SUM(). However, SUM() may not be specified for a nullable column. The statement may not specify HAVING, CUBE, or ROLLUP.</li>
<li>A projected column in the SELECT statement that is used as a simple expression must not appear more than once.</li>
<li>The statement must not include PIVOT or UNPIVOT operators.</li>
<li>The statement must not include the UNION, INTERSECT, or EXCEPT operators.</li>
<li>The statement must not reference a view.</li>
<li>The statement must not contain any of the following: DISTINCT, COMPUTE or COMPUTE BY, or INTO.</li>
<li>The statement must not reference server global variables (@@variable_name).</li>
<li>The statement must not reference derived tables, temporary tables, or table variables.</li>
<li>The statement must not reference tables or views from other databases or servers.</li>
<li>The statement must not contain subqueries, outer joins, or self-joins.</li>
<li>The statement must not reference the large object types: text, ntext, and image.</li>
<li>The statement must not use the CONTAINS or FREETEXT full-text predicates.</li>
<li>The statement must not use rowset functions, including OPENROWSET and OPENQUERY.</li>
<li>The statement must not use any of the following aggregate functions: AVG, COUNT(*), MAX, MIN, STDEV, STDEVP, VAR, or VARP.</li>
<li>The statement must not use any nondeterministic functions, including ranking and windowing functions.</li>
<li>The statement must not contain user-defined aggregates.</li>
<li>The statement must not reference system tables or views, including catalog views and dynamic management views.</li>
<li>The statement must not include FOR BROWSE information.</li>
<li>The statement must not reference a queue.</li>
<li>The statement must not contain conditional statements that cannot change and cannot return results (for example, WHERE 1=0).</li>
<li>The statement can not specify READPAST locking hint.</li>
<li>The statement must not reference any Service Broker QUEUE.</li>
<li>The statement must not reference synonyms.</li>
<li>The statement must not have comparison or expression based on double/real data types.</li>
<li>The statement must not use the TOP expression.</li>
</ul>
</blockquote>
<p>Although this list of restrictions is pretty severe, there is still room left for plenty of useful queries than can be cached using SqlDependency notifications for invalidation.</p>
<h1>Linq to SQL</h1>
<p>Straight forward LINQ to SQL queries are valid for Query Notifications, as long as the first restriction listed above is cleared: <i>table names must be qualified with two-part names</i>. In practice, this means simply fully qualifying the table names in the context designer, or in the [Table] attribute on the class. that is, always use &#8216;dbo.Table&#8217; instead of  simply &#8216;Table&#8217; (of course, replace &#8216;dbo&#8217; with appropriate schema if necessary).</p>
<p>But there are a couple of conditions that are specially important for us: <i>must not use the TOP expression</i> and <i>must not use &#8230; ranking and windowing functions.</i>. These two restrictions mean the popular <code>Skip()</code> and <code>Take()</code> operators are not supported. Unfortunately, these are some of the most popular operators used with LINQ because they are the easiest way to implement paging of results.</p>
<h1>LINQ to Entity Framework</h1>
<p>My initial goal was to only support LINQ to SQL, given that the overwhelming majority of developers favor it over EF. But the implementation works with <i>any</i> IQueryable, so in theory it should just work with EF as well. Unfortunately, the way EF chooses to formulate the queries makes it incompatible with Query Notifications. Consider a simple Linq TO EF query like following:</p>
<p><code>
<pre>var q = from p in ctx.Persons where p.FirstName == "Remus" select p;</pre>
<p></code></p>
<p>This will generate the following SQL:</p>
<p><code></p>
<pre>
SELECT
[Extent1].[PersonId] AS [PersonId],
[Extent1].[FirstName] AS [FirstName],
[Extent1].[LastName] AS [LastName]
FROM (SELECT
      [Persons].[PersonId] AS [PersonId],
      [Persons].[FirstName] AS [FirstName],
      [Persons].[LastName] AS [LastName]
      FROM [dbo].[Persons] AS [Persons]) AS [Extent1]
WHERE 'Remus' = [Extent1].[FirstName]
</pre>
<p></code></p>
<p>The gratuitous addition of a subquery violates the Query Notifications restrictions and the SqlDependency gets invalidated straight away with a Statement violation.</p>
<h1>Download</h1>
<p>The LinqToCache DLLs and source code are available at <a href="http://code.google.com/p/linqtocache/" target="_blank">http://code.google.com/p/linqtocache/</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://rusanu.com/2010/08/04/sqldependency-based-caching-of-linq-queries/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Remote Desktop Manager now available</title>
		<link>http://rusanu.com/2010/06/29/remote-desktop-manager-now-available/</link>
		<comments>http://rusanu.com/2010/06/29/remote-desktop-manager-now-available/#comments</comments>
		<pubDate>Wed, 30 Jun 2010 05:21:55 +0000</pubDate>
		<dc:creator>remus</dc:creator>
		
		<category><![CDATA[Announcements]]></category>

		<category><![CDATA[rdcman]]></category>

		<category><![CDATA[rdp]]></category>

		<category><![CDATA[remote desktop]]></category>

		<category><![CDATA[terminal]]></category>

		<guid isPermaLink="false">http://rusanu.com/?p=835</guid>
		<description><![CDATA[Microsoft internal folks have been used for years a little tool called the Remote Desktop Manager. This tool allows you to save connection settings for frequently used machines you remote into. You can group the servers, save the credentials used for each server or for each group. It allows you to tile and monitor multiple [...]]]></description>
			<content:encoded><![CDATA[<p>Microsoft internal folks have been used for years a little tool called the Remote Desktop Manager. This tool allows you to save connection settings for frequently used machines you remote into. You can group the servers, save the credentials used for each server or for each group. It allows you to tile and monitor multiple remote desks at once, and overall is a wonderful tool for anyone using remote desktops frequently.</p>
<p>Fortunately now the tool is available publicly for download from the <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=4603c621-6de7-4ccb-9f51-d53dc7e48047&#038;displaylang=en" target="_blank">Microsoft Download</a> site.</p>
]]></content:encoded>
			<wfw:commentRss>http://rusanu.com/2010/06/29/remote-desktop-manager-now-available/feed/</wfw:commentRss>
		</item>
		<item>
		<title>High Volume Contiguos Real Time Audit and ETL</title>
		<link>http://rusanu.com/2010/06/11/high-volume-contiguos-real-time-audit/</link>
		<comments>http://rusanu.com/2010/06/11/high-volume-contiguos-real-time-audit/#comments</comments>
		<pubDate>Fri, 11 Jun 2010 18:31:18 +0000</pubDate>
		<dc:creator>remus</dc:creator>
		
		<category><![CDATA[Announcements]]></category>

		<category><![CDATA[data warehouse]]></category>

		<category><![CDATA[etl]]></category>

		<category><![CDATA[nap]]></category>

		<category><![CDATA[nps]]></category>

		<category><![CDATA[radius]]></category>

		<category><![CDATA[service broker]]></category>

		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://rusanu.com/?p=829</guid>
		<description><![CDATA[Tomorrow at SQL Saturday #43 in Redmond I&#8217;ll be presenting a session documenting the real-time audit and ETL the Microsoft uses to manage the access policies on its network. This presentation goes over some of the challenges posed by a contiguos, non-stop, high trhoughput stream of audit records poses when loading the audit into a [...]]]></description>
			<content:encoded><![CDATA[<p>Tomorrow at SQL Saturday #43 in Redmond I&#8217;ll be presenting a session documenting the real-time audit and ETL the Microsoft uses to manage the access policies on its network. This presentation goes over some of the challenges posed by a contiguos, non-stop, high trhoughput stream of audit records poses when loading the audit into a data warehouse. I&#8217;m posting here the slides I&#8217;m going to present, if you plan to attent you can preview them right now, and come to the session with an educated set of questions for your specific case.</p>
<div style="width:425px" id="__ss_4477352"><strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/rusanu/high-volume-real-time-contiguous-etl-and-audit" title="High volume real time contiguous etl and audit">High volume real time contiguous etl and audit</a></strong><object id="__sse4477352" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=highvolumerealtimecontiguousetlandaudit-100611132027-phpapp01&#038;stripped_title=high-volume-real-time-contiguous-etl-and-audit" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed name="__sse4477352" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=highvolumerealtimecontiguousetlandaudit-100611132027-phpapp01&#038;stripped_title=high-volume-real-time-contiguous-etl-and-audit" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object>
<div style="padding:5px 0 12px">View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/rusanu">Remus Rusanu</a>.</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://rusanu.com/2010/06/11/high-volume-contiguos-real-time-audit/feed/</wfw:commentRss>
		</item>
		<item>
		<title>The puzzle of U locks in deadlock graphs</title>
		<link>http://rusanu.com/2010/05/12/the-puzzle-of-u-locks-in-deadlock-graphs/</link>
		<comments>http://rusanu.com/2010/05/12/the-puzzle-of-u-locks-in-deadlock-graphs/#comments</comments>
		<pubDate>Wed, 12 May 2010 21:15:12 +0000</pubDate>
		<dc:creator>remus</dc:creator>
		
		<category><![CDATA[Troubleshooting]]></category>

		<category><![CDATA[deadlock]]></category>

		<category><![CDATA[sql server]]></category>

		<category><![CDATA[update lock]]></category>

		<guid isPermaLink="false">http://rusanu.com/?p=801</guid>
		<description><![CDATA[In a stackoverflow.com question the user has asked how come a SELECT statement could own a U mode lock?
The deadlock indeed suggests that the deadlock victim, a SELECT statement, is owning an U lock on the PK_B index. Why would a SELECT own an U lock? The query had no table hints and was a [...]]]></description>
			<content:encoded><![CDATA[<p>In a <a href="http://stackoverflow.com/questions/2814377/deadlock-problem-because-of-an-update-lock/2814743#2814743" target="_blank">stackoverflow.com question</a> the user has asked how come a SELECT statement could own a U mode lock?</p>
<div id="attachment_802" class="wp-caption alignnone" style="width: 310px"><a href="http://rusanu.com/wp-content/uploads/2010/05/deadlock-sux.png"><img src="http://rusanu.com/wp-content/uploads/2010/05/deadlock-sux-300x62.png" alt="S-U-X deadlock graph" title="deadlock-sux" width="300" height="62" class="size-medium wp-image-802" /></a><p class="wp-caption-text">S-U-X deadlock graph</p></div>
<p>The deadlock indeed suggests that the deadlock victim, a SELECT statement, is owning an U lock on the PK_B index. Why would a SELECT own an U lock? The query had no table hints and was a standalone query, not part of a multi-statement transaction that could had aquired the U lock in previous staements.</p>
<p>Turns out that the SELECT was actually <strong>not</strong> owning any U lock. The deadlock graph files (the *.xdl files) are in fact XML files and they can be opened as XML and inspected, for a little more detail than the visual deadlock graph visualizer permits. Here is the actual resource list in the deadlock XML:</p>
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: Consolas, "Courier New", Courier, Monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>
<pre class="csharpcode">
<span class="kwrd">&lt;</span><span class="html">resource-list</span><span class="kwrd">&gt;</span>
   <span class="kwrd">&lt;</span><span class="html">keylock</span> <span class="attr">hobtid</span><span class="kwrd">="72057594052411392"</span> <span class="attr">dbid</span><span class="kwrd">="10"</span>
         <span class="attr">objectname</span><span class="kwrd">="A"</span> <span class="attr">indexname</span><span class="kwrd">="PK_A"</span> <span class="attr">id</span><span class="kwrd">="lock17ed4040"</span>
        <span class="attr">mode</span><span class="kwrd">="X"</span> <span class="attr">associatedObjectId</span><span class="kwrd">="72057594052411392"</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">owner-list</span><span class="kwrd">&gt;</span>
     <span class="kwrd">&lt;</span><span class="html">owner</span> <span class="attr">id</span><span class="kwrd">="process4f5d000"</span> <span class="attr">mode</span><span class="kwrd">="X"</span><span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;/</span><span class="html">owner-list</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">waiter-list</span><span class="kwrd">&gt;</span>
     <span class="kwrd">&lt;</span><span class="html">waiter</span> <span class="attr">id</span><span class="kwrd">="processfa3c8e0"</span> <span class="attr">mode</span><span class="kwrd">="S"</span> <span class="attr">requestType</span><span class="kwrd">="wait"</span><span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;/</span><span class="html">waiter-list</span><span class="kwrd">&gt;</span>
   <span class="kwrd">&lt;/</span><span class="html">keylock</span><span class="kwrd">&gt;</span>
   <span class="kwrd">&lt;</span><span class="html">keylock</span> <span class="attr">hobtid</span><span class="kwrd">="72057594051166208"</span> <span class="attr">dbid</span><span class="kwrd">="10"</span>
        <span class="attr">objectname</span><span class="kwrd">="B"</span> <span class="attr">indexname</span><span class="kwrd">="PK_B"</span> <span class="attr">id</span><span class="kwrd">="lock22ea3940"</span>
        <span class="attr">mode</span><span class="kwrd">="U"</span> <span class="attr">associatedObjectId</span><span class="kwrd">="72057594051166208"</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">owner-list</span><span class="kwrd">&gt;</span>
     <span class="kwrd">&lt;</span><span class="html">owner</span> <span class="attr">id</span><span class="kwrd">="processfa3c8e0"</span> <span class="attr">mode</span><span class="kwrd">="S"</span><span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;/</span><span class="html">owner-list</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">waiter-list</span><span class="kwrd">&gt;</span>
     <span class="kwrd">&lt;</span><span class="html">waiter</span> <span class="attr">id</span><span class="kwrd">="process4f5d000"</span> <span class="attr">mode</span><span class="kwrd">="X"</span> <span class="attr">requestType</span><span class="kwrd">="convert"</span><span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;/</span><span class="html">waiter-list</span><span class="kwrd">&gt;</span>
   <span class="kwrd">&lt;/</span><span class="html">keylock</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;/</span><span class="html">resource-list</span><span class="kwrd">&gt;</span></pre>
<p>As you can see, the resource lock22ea3940 is owned by the process processfa3c8e0 (the SELECT) indeed, but is owned in <strong>S</strong> mode. The process process4f5d000 (the UPDATE) is requesting this resource for a <strong>convert</strong> from U to X mode. So the true deadlock is like this:</p>
<ul>
<li>SELECT owns a lock on the row in PK_B in S mode</li>
<li>SELECT wants a lock on the row in PK_A in S mode</li>
<li>UPDATE owns a lock on the row in PK_A in X mode</li>
<li>UPDATE also owns a U lock on the PK_B row. (S and U modes are compatible)</li>
<li>UPDATE is requesting a convert of the U lock it has on the row on PK_B to X mode</li>
</ul>
<p>As you can see, there is no mysterious U lock owned by the SELECT. There is an U lock on the row in PK_B, but is owned by the UPDATE, which is requesting a convert to X for it. The fact that the resource is showned in the deadlock graph viewer in SSMS as being &#8216;Owner mode: U&#8217; and pointing to the SELECT is simply an artifact of how SSMS displays the deadlock graph.</p>
<p>The lesson to take home is that the visual graphic deadlock graph display is usefull only to have a cursory glance at the deadlock cycle. The true meat and potatoes are in the XML, which has a lot more information. Not to mention that the information in the XML is actually correct, which helps investigation&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://rusanu.com/2010/05/12/the-puzzle-of-u-locks-in-deadlock-graphs/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Effective Speakers at Portland #devsat and #sqlsat27</title>
		<link>http://rusanu.com/2010/05/11/effective-speakers-at-portland-devsat-and-sqlsat27/</link>
		<comments>http://rusanu.com/2010/05/11/effective-speakers-at-portland-devsat-and-sqlsat27/#comments</comments>
		<pubDate>Wed, 12 May 2010 05:52:20 +0000</pubDate>
		<dc:creator>remus</dc:creator>
		
		<category><![CDATA[Announcements]]></category>

		<category><![CDATA[devsat]]></category>

		<category><![CDATA[portland]]></category>

		<category><![CDATA[session]]></category>

		<category><![CDATA[speaker]]></category>

		<category><![CDATA[sql saturday]]></category>

		<category><![CDATA[sqlsat27]]></category>

		<guid isPermaLink="false">http://rusanu.com/?p=792</guid>
		<description><![CDATA[Which is faster: ++i or i++?
In 1998 I was looking to change jobs and I interviewed with a company for a C++ developer position. The interview went well and as we were approaching the end, one of the interviewers asked me this question: which is faster ++i or i++? I pondered the question a second, [...]]]></description>
			<content:encoded><![CDATA[<p>Which is faster: <tt>++i</tt> or <tt>i++</tt>?</p>
<p>In 1998 I was looking to change jobs and I interviewed with a company for a C++ developer position. The interview went well and as we were approaching the end, one of the interviewers asked me this question: which is faster ++i or i++? I pondered the question a second, then the other interviewer said that is probably implementation specific. The first one corrected him that i++ must return the value before the increment therefore it must make a copy of itself, while ++i returns the value after the increment therefore does not need to make a copy of itself, it can return itself. With this my chance to actually answer the question and their chance to see how I approach the problem were gone, but the interview was finished anyway as we were out of time. I got the offer from them, yet I ended up with a different company. But that question lingered in my mind, I though what a clever little thing to know. Few months later I got my hands on the <a href="http://www.aristeia.com/books.html" target="_blank">Effective C++</a> book by Scott Meyers, and this opened my appetite for the follow up book More Effective C++. And there it was, item 6 in More Effective C++: <i>Distinguish between prefix and postfix forms of forms of increment and decrement operators</i>.</p>
<p>These two books were tremendously important in forming me as a professional C++ developer. They got me starting in studying C++ more deeply, beyond what I had to use in my day to day job. I ended up taking a Brainbench C++ test and I scored in the top 10 worldwide, which pretty soon landed me an email from Microsoft recruiting. The rest, as they say, is history.</p>
<p>SQL Saturday #27 is going to be held on May 22 in Portland and will share the venue with Portland CodeCamp. The list of speakers is really impressive, and amongst them, you guessed, is Scott Meyers presenting <a href="http://portlandcodecamp.org/2010/Sessions/Details/77" target="_blank">CPU Caches and Why You Care</a>. There are many more fine speakers and interesting topics for every taste, and the event is free. Is worth your time if you&#8217;re in the area, and well worth a trip to the City of Roses if you&#8217;re not.</p>
<p>I myself will be presenting a session on <a href="http://sqlsaturday.com/viewsession.aspx?sat=27&#038;sessionid=1708" target="_blank">High Volume Real Time Contiguous ETL and Audit</a>.</p>
<p>To register with the CodeCamp and SQL Saturday events go to <a href="http://devsat.eventbrite.com">http://devsat.eventbrite.com</a></p>
]]></content:encoded>
			<wfw:commentRss>http://rusanu.com/2010/05/11/effective-speakers-at-portland-devsat-and-sqlsat27/feed/</wfw:commentRss>
		</item>
		<item>
		<title>SQL Server 2008 R2 Express database size limit: 10GB</title>
		<link>http://rusanu.com/2010/04/28/sql-server-2008-r2-express-database-size-limit-10gb/</link>
		<comments>http://rusanu.com/2010/04/28/sql-server-2008-r2-express-database-size-limit-10gb/#comments</comments>
		<pubDate>Wed, 28 Apr 2010 17:11:11 +0000</pubDate>
		<dc:creator>remus</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[database size]]></category>

		<category><![CDATA[express]]></category>

		<category><![CDATA[limitations]]></category>

		<category><![CDATA[sql server]]></category>

		<guid isPermaLink="false">http://rusanu.com/?p=788</guid>
		<description><![CDATA[The SQL Server 2008 R2 Express editions has increased the database size limit to 10Gb from the previous limit of 4Gb. This is great news for many developers, as the 4Gb limitation was by far the most difficult barrier preventing Express adoption. With today&#8217;s rate of generating data, the 4Gb limit was just plain small.
All [...]]]></description>
			<content:encoded><![CDATA[<p>The SQL Server 2008 R2 Express editions has increased the database size limit to 10Gb from the previous limit of 4Gb. This is great news for many developers, as the 4Gb limitation was by far the most difficult barrier preventing Express adoption. With today&#8217;s rate of generating data, the 4Gb limit was just plain small.</p>
<p>All the other limitations of SQL Server Express stay in place:</p>
<dl>
<dt>CPU</dt>
<dd>SQL Server Express only uses once CPU socket. It will use all cores and any Hyper-Threading logical processor in that socket though.</dd>
<dt>Memory</dt>
<dd>SQL Server Express limits the size of the data buffer pool to 1Gb.</dd>
<dt>Replication</dt>
<dd>SQL Server Express can only participate as a subscriber in a replication topology.</dd>
<dt>Service Broker</dt>
<dd>Two SQL Server Express instances cannot exchange Service Broker messages directly, the messages have to be routed through a higher level SKU.</dd>
<dt>SQL Agent</dt>
<dd>SQL Server Express does not have an Agent service and as such it cannot run Agent scheduled jobs.</dd>
</dl>
]]></content:encoded>
			<wfw:commentRss>http://rusanu.com/2010/04/28/sql-server-2008-r2-express-database-size-limit-10gb/feed/</wfw:commentRss>
		</item>
		<item>
		<title>How to change database mirroring encryption with minimal downtime</title>
		<link>http://rusanu.com/2010/04/23/how-to-change-database-mirroring-encryption-with-minimal-downtime/</link>
		<comments>http://rusanu.com/2010/04/23/how-to-change-database-mirroring-encryption-with-minimal-downtime/#comments</comments>
		<pubDate>Fri, 23 Apr 2010 19:33:13 +0000</pubDate>
		<dc:creator>remus</dc:creator>
		
		<category><![CDATA[Tutorials]]></category>

		<category><![CDATA[database mirroring]]></category>

		<category><![CDATA[downtime]]></category>

		<category><![CDATA[encryption]]></category>

		<category><![CDATA[endpoint]]></category>

		<category><![CDATA[sql server]]></category>

		<guid isPermaLink="false">http://rusanu.com/?p=764</guid>
		<description><![CDATA[SQL Server Database Mirroring uses an encrypted connection to ship the data between the principal and the mirror. By default RC4 encryption is enabled and used. The endpoint can be configured to use AES encryption instead, or no encryption. The overhead of using RC4 encryption is quite small, the overhead of using AES encryption is [...]]]></description>
			<content:encoded><![CDATA[<p>SQL Server Database Mirroring uses an encrypted connection to ship the data between the principal and the mirror. By default RC4 encryption is enabled and used. The endpoint can be configured to use AES encryption instead, or no encryption. The overhead of using RC4 encryption is quite small, the overhead of using AES encryption is slightly bigger, but not significant. Under well understood conditions, like inside a secured data center, encryption can be safely turned off for a 5-10% increase in speed in mirroring traffic. Note that even with encryption turned off, the traffic is still cryptographically signed (HMAC). Traffic signing cannot be turned off.</p>
<p>To change the encryption used by an endpoint, one has to run the <a href="http://technet.microsoft.com/en-us/library/ms186332.aspx" target="_blank">ALTER ENDPOINT &#8230; FOR DATABASE_MIRRORING (ENCRYPTION = {DISABLED|SUPPORTED|REQUIRED})</a>. Two endpoints must have compatible encryption settings to be able to communicate. The following table shows the compatibility matrix of encryption settings:</p>
<table style="width:90%; margin-left:auto;margin-right:auto;border: 1px solid #ccc;border-collapse:collapse">
<colgroup>
<col width="25%" style="background-color:lightgray"/><br />
<col width="25%"/><br />
<col width="25%"/><br />
<col width="25%"/><br />
</colgroup>
<thead>
<tr style="background-color:lightgray">
<th style="background-color:white"/>
<th>DISABLED</th>
<td>SUPPORTED</th>
<th>REQUIRED</th>
</tr>
</thead>
<tbody>
<tr>
<td>DISABLED</td>
<td>CLEAR</td>
<td>CLEAR</td>
<td>-</td>
</tr>
<tr>
<td>SUPPORTED</td>
<td>CLEAR</td>
<td>ENCRYPTED</td>
<td>ENCRYPTED</td>
</tr>
<tr>
<td>REQUIRED</td>
<td>-</td>
<td>ENCRYPTED</td>
<td>ENCRYPTED</td>
</tr>
</tbody>
</table>
<p>The default setting for an endpoint is ENCRYPTION = REQUIRED, which enforces encryption and refuses to connect to an endpoint that has disabled encryption.</p>
<h2>Changing encryption settings on an existing endpoint</h2>
<p>If you have a running mirroring session and want to change the settings to squeeze the extra 5-10% you can expect from removing RC4 encryption, then chances are you deployed the endpoint with the default encryption settings, namely REQUIRED. If you don&#8217;t know the current endpoint settings you can always check the <a href="http://msdn.microsoft.com/en-us/library/ms190278.aspx" target="_blank">sys.database_mirroring_endpoints</a> metadata catalog. When encryption is REQUIRED the encryption_algorithm column is one of 1,2,5 or 6. When encryption is SUPPORTED the encryption_algorithm column is one of 3,4,7 or 8. When is DISABLED the encryption_algorithm is 0 and the is_encryption_Enabled column changes to 0. To force the traffic to be unencrypted at least one endpoint has to have ENCRYPTION = DISABLED.</p>
<p>When you run the ALTER ENDPOINT statement and change the encryption settings the endpoint is going to be stopped and restarted during the ALTER statement. All existing connections will be disconnected. A database mirroring session may immediately re-connect and not react to this short disruption in any fashion visible to the user.</p>
<p>The safest way to change an existing mirroring session that uses encryption to no longer encrypt the traffic, when there is no witness, would be like this:</p>
<ol>
<li>Change the mirror endpoint to SUPPORTED</li>
<li>Change the principal endpoint to DISABLED</li>
<li>Change the mirror endpoint to DISABLED</li>
<li>Verify that the connections are unencrypted, check encryption_algorithm column in the <a href="http://technet.microsoft.com/en-us/library/ms189796.aspx" target="_blank">sys.dm_db_mirroring_connections</a> DMV.</li>
</ol>
<p>If a the mirroring session involves a witness, then it too must have the endpoint set to a compatible encryption setting:</p>
<ol>
<li>Change the witness endpoint to SUPPORTED</li>
<li>Change the mirror endpoint to SUPPORTED</li>
<li>Change the principal endpoint to DISABLED</li>
<li>Change the witness endpoint to DISABLED</li>
<li>Change the mirror endpoint to DISABLED</li>
<li>Verify that the connections are unencrypted, check encryption_algorithm column in the <a href="http://technet.microsoft.com/en-us/library/ms189796.aspx" target="_blank">sys.dm_db_mirroring_connections</a> DMV.</li>
</ol>
<p>Note that if automatic failover is enabled then at the moment the principal endpoint is changed, it is possible for automatic failover to occur, given that for a brief moment the mirror and the witness will have a quorum.</p>
<h2>How to troubleshoot if something goes wrong</h2>
<p>Attach Profiler to all instances involved in the mirroring session and open a trace that listens for the <a href="http://msdn.microsoft.com/en-us/library/ms190746.aspx" target="_blank">Audit Database Mirroring Login Event Class</a> (on SQL 2005 use the <A href="http://msdn.microsoft.com/en-us/library/ms190261%28v=SQL.100%29.aspx" target="_blank">Audit Broker Login Event Class</a> event instead, it <strong>will</strong> trace the DBM sessions). If you did a mistake during the ALTER ENDPOINT changes and ended up with incompatible settings, there will be an event generated visible in Profiler. The event Text will contain an error message explaining why the endpoints cannot connect.</p>
]]></content:encoded>
			<wfw:commentRss>http://rusanu.com/2010/04/23/how-to-change-database-mirroring-encryption-with-minimal-downtime/feed/</wfw:commentRss>
		</item>
		<item>
		<title>What is Remus up to?</title>
		<link>http://rusanu.com/2010/04/01/what-is-remus-up-to/</link>
		<comments>http://rusanu.com/2010/04/01/what-is-remus-up-to/#comments</comments>
		<pubDate>Fri, 02 Apr 2010 05:20:32 +0000</pubDate>
		<dc:creator>remus</dc:creator>
		
		<category><![CDATA[Announcements]]></category>

		<guid isPermaLink="false">http://rusanu.com/?p=754</guid>
		<description><![CDATA[Some of you already know this: I am again FTE with Microsoft. I was in a contract for a very interesting project with Microsoft IT over the past months in a vendor position, and getting back in touch with the cool stuff that goes on inside Microsoft kindled back the passion for bold projects with [...]]]></description>
			<content:encoded><![CDATA[<p>Some of you already know this: I am again FTE with Microsoft. I was in a contract for a very interesting project with Microsoft IT over the past months in a vendor position, and getting back in touch with the cool stuff that goes on inside Microsoft kindled back the passion for bold projects with big impact. Since March 29 I&#8217;m working again as a developer with what is officially known as the SQL RDBMS Core Team. I&#8217;m no longer involved with the Service Broker though, I now work on the Access Methods. Indexes, BTrees, Heaps and lets not forget DBCC. Fun stuff.</p>
]]></content:encoded>
			<wfw:commentRss>http://rusanu.com/2010/04/01/what-is-remus-up-to/feed/</wfw:commentRss>
		</item>
		<item>
		<title>The Bizzaro Guide to SQL Server Performance</title>
		<link>http://rusanu.com/2010/03/31/the-bizzaro-guide-to-sql-server-performance/</link>
		<comments>http://rusanu.com/2010/03/31/the-bizzaro-guide-to-sql-server-performance/#comments</comments>
		<pubDate>Wed, 31 Mar 2010 08:28:16 +0000</pubDate>
		<dc:creator>remus</dc:creator>
		
		<category><![CDATA[Troubleshooting]]></category>

		<category><![CDATA[april fool]]></category>

		<category><![CDATA[humour]]></category>

		<category><![CDATA[performance]]></category>

		<category><![CDATA[sql optimization]]></category>

		<guid isPermaLink="false">http://rusanu.com/?p=747</guid>
		<description><![CDATA[Some say performance troubleshooting is a difficult science that blends just the right amount of patience, knowledge and experience. But I say forget all that, a few bullet points can get you a long way in fixing any problem you encounter. Is more important to find a google SEO friendly result that gives simplistic advice. [...]]]></description>
			<content:encoded><![CDATA[<p>Some say performance troubleshooting is a difficult science that blends just the right amount of patience, knowledge and experience. But I say forget all that, a few bullet points can get you a long way in fixing any problem you encounter. Is more important to find a google SEO friendly result that gives simplistic advice. Most importantly, good advice never contains the words &#8216;It depends&#8217;. Without further ado, here is my bulletproof SQL Server optimization guide:</p>
<ul>
<li><b>Always trust your gut feeling.</b> Avoid doing costly and unnecessary measurements. They may lead down the treacherous path of the scientific method. A gut feeling is always easier to explain and this improves communication. Measurements require use of complicated notions not everybody understands, so they lead to conflicts in the team.</li>
<li><b>High CPU utilization is caused by index fragmentation.</b> Because the distance between database pages increases, the processor needs more cycles to reference the pages in the buffer pool.</li>
<li><b>Low CPU utilization is caused by index fragmentation.</b> As the index fragments get smaller, they fit better into the processor L2 cache and this results in fewer cycles needed to access the row slots in the page. Because the data is in the cache the processor idles next cycles, resulting in low CPU utilization.</li>
<li><b>High Avg. Disk Sec. per Transfer is caused by index fragmentation.</b> When indexes are fragmented the disk controller has to reorder the IO scatter-gather requests to put them in descending order. Needles to say, this operation increases the transfer times in geometric progression, because all the commercial disk controllers use bubble sort for this operation.</li>
<li><b>High memory consumption is caused by index fragmentation.</b> This is fairly trivial and well known, but I&#8217;ll repeat it here: as the number of index fragments increases more pointers are needed to keep track of each fragment. Pointers are stored in virtual memory and virtual memory is very large, and this causes high memory consumption.</li>
<li><b>Syntax errors are caused by index fragmentation.</b> Because the syntax is verified using the metadata catalogs, high fragmentation in the database can leave gaps in the syntax. This is turn causes the parser to generate syntax errors on perfectly valid statements like SECLET and UPTADE.</li>
<li><b>Covering indexes can lead to index fragmentation.</b> Covering indexes are the indexes used by the query optimizer to cover itself in case the plan has execution faults. Because they are so often read they wear off and start to fragment.</li>
<li><b>Index fragmentation can be resolved by shrinking the database</b>. As the data pages are squeezed tighter during the shrinking, they naturally realign themselves in the correct order.</li>
</ul>
<p>There you have it, the simplest troubleshooting guide. Since most performance problems are caused by index fragmentation, all you have to do is shrink the database to force the pages to re-align correctly, and this will resolve the performance problem.</p>
<p>Happy April 1st everyone!</p>
]]></content:encoded>
			<wfw:commentRss>http://rusanu.com/2010/03/31/the-bizzaro-guide-to-sql-server-performance/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Using tables as Queues</title>
		<link>http://rusanu.com/2010/03/26/using-tables-as-queues/</link>
		<comments>http://rusanu.com/2010/03/26/using-tables-as-queues/#comments</comments>
		<pubDate>Fri, 26 Mar 2010 19:02:49 +0000</pubDate>
		<dc:creator>remus</dc:creator>
		
		<category><![CDATA[Samples]]></category>

		<category><![CDATA[Tutorials]]></category>

		<category><![CDATA[delete]]></category>

		<category><![CDATA[heap]]></category>

		<category><![CDATA[output clause]]></category>

		<category><![CDATA[pattern]]></category>

		<category><![CDATA[producer consumer]]></category>

		<category><![CDATA[queues]]></category>

		<category><![CDATA[sql]]></category>

		<category><![CDATA[stack]]></category>

		<category><![CDATA[table]]></category>

		<category><![CDATA[transact-sql]]></category>

		<category><![CDATA[tsql]]></category>

		<guid isPermaLink="false">http://rusanu.com/?p=682</guid>
		<description><![CDATA[A very common question asked on all programming forums is how to implement queues based on database tables. This is not a trivial question actually. Implementing a queue backed by a table is notoriously difficult, error prone and susceptible to deadlocks. Because queues are usually needed as a link between various processing stages in a [...]]]></description>
			<content:encoded><![CDATA[<p>A very common question asked on all programming forums is how to implement queues based on database tables. This is not a trivial question actually. Implementing a queue backed by a table is notoriously difficult, error prone and susceptible to deadlocks. Because queues are usually needed as a link between various processing stages in a workflow they operate in highly concurrent environments where multiple processes enqueue rows into the table while multiple processes attempt to dequeue these rows. This concurrency creates correctness, scalability and performance challenges.</p>
<p>But since SQL Server 2005 introduced the OUTPUT clause, using tables as queues is no longer a hard problem. This fact is called out in the <a href="http://msdn.microsoft.com/en-us/library/ms177564.aspx" target="_blank">OUTPUT Clause</a> topic in BOL:</p>
<blockquote><p>You can use OUTPUT in applications that use tables as queues, or to hold intermediate result sets. That is, the application is constantly adding or removing rows from the table&#8230; Other semantics may also be implemented, such as using a table to implement a stack.</p></blockquote>
<p>The reason why OUTPUT clause is critical is that it offers an atomic destructive read operation that allows us to remove the dequeued row <i>and</i> return it to the caller, in one single statement.</p>
<h2><a name="HeapQueue">Heap Queues</a></h2>
<p>The simplest queue is a heap: producers can equeue into the heap and consumers can dequeue, but order of operations is not important: the consumers can dequeue <i>any</i> row, as long as it is unlocked.</p>
<p><code></p>
<pre>
<span style="color: Black"></span><span style="color:Blue">create</span><span style="color:Black">&nbsp;</span><span style="color:Blue">table</span><span style="color:Black">&nbsp;HeapQueue&nbsp;</span><span style="color:Gray">(
</span><span style="color:Black">&nbsp;&nbsp;Payload&nbsp;</span><span style="color:Blue">varbinary</span><span style="color:Gray">(</span><span style="color:Fuchsia">max</span><span style="color:Gray">));
</span><span style="color:Black">go

</span><span style="color:Blue">create</span><span style="color:Black">&nbsp;</span><span style="color:Blue">procedure</span><span style="color:Black">&nbsp;usp_enqueueHeap
&nbsp;&nbsp;@payload&nbsp;</span><span style="color:Blue">varbinary</span><span style="color:Gray">(</span><span style="color:Fuchsia">max</span><span style="color:Gray">)
</span><span style="color:Blue">as
</span><span style="color:Black">&nbsp;&nbsp;</span><span style="color:Blue">set</span><span style="color:Black">&nbsp;</span><span style="color:Blue">nocount</span><span style="color:Black">&nbsp;</span><span style="color:Blue">on</span><span style="color:Gray">;
</span><span style="color:Black">&nbsp;&nbsp;</span><span style="color:Blue">insert</span><span style="color:Black">&nbsp;</span><span style="color:Blue">into</span><span style="color:Black">&nbsp;HeapQueue&nbsp;</span><span style="color:Gray">(</span><span style="color:Black">Payload</span><span style="color:Gray">)</span><span style="color:Black">&nbsp;</span><span style="color:Blue">values</span><span style="color:Black">&nbsp;</span><span style="color:Gray">(</span><span style="color:Black">@Payload</span><span style="color:Gray">);
</span><span style="color:Black">go

</span><span style="color:Blue">create</span><span style="color:Black">&nbsp;</span><span style="color:Blue">procedure</span><span style="color:Black">&nbsp;usp_dequeueHeap&nbsp;
</span><span style="color:Blue">as
</span><span style="color:Black">&nbsp;&nbsp;</span><span style="color:Blue">set</span><span style="color:Black">&nbsp;</span><span style="color:Blue">nocount</span><span style="color:Black">&nbsp;</span><span style="color:Blue">on</span><span style="color:Gray">;
</span><span style="color:Black">&nbsp;&nbsp;</span><span style="color:Blue">delete</span><span style="color:Black">&nbsp;</span><span style="color:Blue">top</span><span style="color:Gray">(</span><span style="color:Black">1</span><span style="color:Gray">)</span><span style="color:Black">&nbsp;</span><span style="color:Blue">from</span><span style="color:Black">&nbsp;HeapQueue&nbsp;</span><span style="color:Blue">with</span><span style="color:Black">&nbsp;</span><span style="color:Gray">(</span><span style="color:Blue">rowlock</span><span style="color:Gray">,</span><span style="color:Black">&nbsp;</span><span style="color:Blue">readpast</span><span style="color:Gray">)
</span><span style="color:Black">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color:Blue">output</span><span style="color:Black">&nbsp;deleted</span><span style="color:Gray">.</span><span style="color:Black">payload</span><span style="color:Gray">;</span><span style="color:Black">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
go</span>
</pre>
<p></code></p>
<p>A heap queue can satisfy most producer-consumer patterns. It scales well and is very simple to implement and understand. Notice the (rowlock, readpast) hints on the delete operation, they allow for concurrent consumers to dequeue rows from the table without blocking each other. <b>A heap queue makes no order guarantees</b>.</p>
<h2><a name="FifoQueues">FIFO Queues</a></h2>
<p>When he queueing and dequeuing operations have to support a certain order two changes have to be made:</p>
<ul>
<li>The table must be organized as a clustered index ordered by a key that preserves the desired dequeue order.</li>
<li>The dequeue operation must contain an ORDER BY clause to guarantee the order.</li>
</ul>
<p><code></p>
<pre>
<span style="color: Black"></span><span style="color:Blue">create</span><span style="color:Black">&nbsp;</span><span style="color:Blue">table</span><span style="color:Black">&nbsp;FifoQueue&nbsp;</span><span style="color:Gray">(
</span><span style="color:Black">&nbsp;&nbsp;Id&nbsp;</span><span style="color:Blue">bigint</span><span style="color:Black">&nbsp;</span><span style="color:Gray">not</span><span style="color:Black">&nbsp;</span><span style="color:Gray">null</span><span style="color:Black">&nbsp;</span><span style="color:Blue">identity</span><span style="color:Gray">(</span><span style="color:Black">1</span><span style="color:Gray">,</span><span style="color:Black">1</span><span style="color:Gray">),
</span><span style="color:Black">&nbsp;&nbsp;Payload&nbsp;</span><span style="color:Blue">varbinary</span><span style="color:Gray">(</span><span style="color:Fuchsia">max</span><span style="color:Gray">));
</span><span style="color:Black">go

</span><span style="color:Blue">create</span><span style="color:Black">&nbsp;</span><span style="color:Blue">clustered</span><span style="color:Black">&nbsp;</span><span style="color:Blue">index</span><span style="color:Black">&nbsp;cdxFifoQueue&nbsp;</span><span style="color:Blue">on</span><span style="color:Black">&nbsp;FifoQueue&nbsp;</span><span style="color:Gray">(</span><span style="color:Black">Id</span><span style="color:Gray">);
</span><span style="color:Black">go

</span><span style="color:Blue">create</span><span style="color:Black">&nbsp;</span><span style="color:Blue">procedure</span><span style="color:Black">&nbsp;usp_enqueueFifo
&nbsp;&nbsp;@payload&nbsp;</span><span style="color:Blue">varbinary</span><span style="color:Gray">(</span><span style="color:Fuchsia">max</span><span style="color:Gray">)
</span><span style="color:Blue">as
</span><span style="color:Black">&nbsp;&nbsp;</span><span style="color:Blue">set</span><span style="color:Black">&nbsp;</span><span style="color:Blue">nocount</span><span style="color:Black">&nbsp;</span><span style="color:Blue">on</span><span style="color:Gray">;
</span><span style="color:Black">&nbsp;&nbsp;</span><span style="color:Blue">insert</span><span style="color:Black">&nbsp;</span><span style="color:Blue">into</span><span style="color:Black">&nbsp;FifoQueue&nbsp;</span><span style="color:Gray">(</span><span style="color:Black">Payload</span><span style="color:Gray">)</span><span style="color:Black">&nbsp;</span><span style="color:Blue">values</span><span style="color:Black">&nbsp;</span><span style="color:Gray">(</span><span style="color:Black">@Payload</span><span style="color:Gray">);
</span><span style="color:Black">go

</span><span style="color:Blue">create</span><span style="color:Black">&nbsp;</span><span style="color:Blue">procedure</span><span style="color:Black">&nbsp;usp_dequeueFifo
</span><span style="color:Blue">as
</span><span style="color:Black">&nbsp;&nbsp;</span><span style="color:Blue">set</span><span style="color:Black">&nbsp;</span><span style="color:Blue">nocount</span><span style="color:Black">&nbsp;</span><span style="color:Blue">on</span><span style="color:Gray">;
</span><span style="color:Black">&nbsp;&nbsp;</span><span style="color:Blue">with</span><span style="color:Black">&nbsp;cte&nbsp;</span><span style="color:Blue">as</span><span style="color:Black">&nbsp;</span><span style="color:Gray">(
</span><span style="color:Black">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color:Blue">select</span><span style="color:Black">&nbsp;</span><span style="color:Blue">top</span><span style="color:Gray">(</span><span style="color:Black">1</span><span style="color:Gray">)</span><span style="color:Black">&nbsp;Payload
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color:Blue">from</span><span style="color:Black">&nbsp;FifoQueue&nbsp;</span><span style="color:Blue">with</span><span style="color:Black">&nbsp;</span><span style="color:Gray">(</span><span style="color:Blue">rowlock</span><span style="color:Gray">,</span><span style="color:Black">&nbsp;</span><span style="color:Blue">readpast</span><span style="color:Gray">)
</span><span style="color:Black">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color:Blue">order</span><span style="color:Black">&nbsp;</span><span style="color:Blue">by</span><span style="color:Black">&nbsp;Id</span><span style="color:Gray">)
</span><span style="color:Black">&nbsp;&nbsp;</span><span style="color:Blue">delete</span><span style="color:Black">&nbsp;</span><span style="color:Blue">from</span><span style="color:Black">&nbsp;cte
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color:Blue">output</span><span style="color:Black">&nbsp;deleted</span><span style="color:Gray">.</span><span style="color:Black">Payload</span><span style="color:Gray">;
</span><span style="color:Black">go</span>
</pre>
<p></code></p>
<p>By adding the IDENTITY column to our queue and making it the clustered index, we can dequeue in the order inserted. The enqueue operation is identical with our Heap Queue, but the dequeue is slightly changed, as the requirement to dequeue in the order inserted means that we have to specify an ORDER BY. Since the DELETE statement does not support ORDER BY, we use a Common Table Expression to select the row to be dequeued, then delete this row and return the payload in the OUTPUT clause. Isn&#8217;t this the same as doing a SELECT followed by a DELETE, and hence exposed to the traditional correctness problems with table backed queues? Technically, it is. But this is a SELECT followed by a DELETE that actually <i>works</i> for table based queues. Let me explain.</p>
<p>Because the query is actually an DELETE of a CTE, the query execution will occur as a DELETE, not as an SELECT followed by a DELETE, and also not as a SELECT executed in the context of the DELETE. The crucial part is that the SELECT part will aquire <b>LCK_M_U</b> update locks on the rows scanned. LCK_M_U is compatible with LCK_M_S shared locks, but is incompatible with another LCK_M_U. So two concurrent dequeue threads will <b>not</b> try to dequeue the same row. One will grab the first row free, the other thread will grab the next row.</p>
<p>Is also worth looking at how a compact plan the usp_dequeueFifo has:</p>
<div id="attachment_699" class="wp-caption alignnone" style="width: 310px"><a href="http://rusanu.com/wp-content/uploads/2010/03/fifoqueueplan.png"><img src="http://rusanu.com/wp-content/uploads/2010/03/fifoqueueplan-300x60.png" alt="usp_dequeueFifo execution plan" title="fifoqueueplan" width="300" height="60" class="size-medium wp-image-699" /></a><p class="wp-caption-text">usp_dequeueFifo execution plan</p></div>
<p>Compare this with the alternative of using a subquery to locate the row to be deleted:</p>
<p><div id="attachment_701" class="wp-caption alignnone" style="width: 310px"><a href="http://rusanu.com/wp-content/uploads/2010/03/subqueryplan.png"><img src="http://rusanu.com/wp-content/uploads/2010/03/subqueryplan-300x71.png" alt="Subquery deque plan" title="subqueryplan" width="300" height="71" class="size-medium wp-image-701" /></a><p class="wp-caption-text">Subquery deque plan</p></div><br />
<code>
<pre>
<span style="color: Black"></span><span style="color:Blue">delete top</span><span style="color:Gray">(</span><span style="color:Black">1</span><span style="color:Gray">) </span><span style="color:Blue">from </span><span style="color:Black">FifoQueue
</span><span style="color:Blue">output </span><span style="color:Black">deleted</span><span style="color:Gray">.</span><span style="color:Black">Payload
</span><span style="color:Blue">where </span><span style="color:Black">Id </span><span style="color:Gray">= (
</span><span style="color:Blue">select top</span><span style="color:Gray">(</span><span style="color:Black">1</span><span style="color:Gray">) </span><span style="color:Black">Id
  </span><span style="color:Blue">from </span><span style="color:Black">FifoQueue </span><span style="color:Blue">with </span><span style="color:Gray">(</span><span style="color:Blue">rowlock</span><span style="color:Gray">, </span><span style="color:Blue">updlock</span><span style="color:Gray">, </span><span style="color:Blue">readpast</span><span style="color:Gray">)
</span><span style="color:Blue">order by </span><span style="color:Black">Id</span><span style="color:Gray">)</span>
</pre>
<p></code></p>
<h3><a name="Concurrency">Strict Ordering and Concurrency</a></h3>
<p>Strict FIFO ordering in a database world would have to take into account transactions. If transaction T1 dequeues row A, transaction T2 dequeues the next row B and then T1 rolls back and T2 commits, the row B was processed out of order. So any dequeue operation would have to wait for the previous dequeue to <b>committ</b> before proceeding. While this is correct, is also highly inefficient, as it means that all transactions must serialize access to the queue. Many applications accept the processing to occur out of order for the sake of achieving a reasonable scalability and performance.</p>
<p>If strict FIFO order is <i>required</i> then you have to <b>remove the readpast</b> hint from the usp_dequeueFifo procedure. When this is done, only one transaction can dequeue rows from the queue at a time. All other transaction will have to wait until the first one commits. This is not an implementation artifact, it is a fundamental requirement derived from the ACID properties of transactions.</p>
<p>If a lax FIFO order is acceptable, then the readpast hint will ensure that multiple transactions can dequeue rows concurrently. However, the strict FIFO order cannot be guaranteed in this case.</p>
<h2><a name="LifoStacks">LIFO Stacks</a></h3>
<p>A stack backed by a queue is also possible. The implementation and table structure is almost identical with the FIFO queue, with one difference: the ORDER BY clause has a DESC.</p>
<p><code>
<pre>
<span style="color:Blue">with</span><span style="color:Black">&nbsp;cte&nbsp;</span><span style="color:Blue">as</span><span style="color:Black">&nbsp;</span><span style="color:Gray">(
</span><span style="color:Black">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color:Blue">select</span><span style="color:Black">&nbsp;</span><span style="color:Blue">top</span><span style="color:Gray">(</span><span style="color:Black">1</span><span style="color:Gray">)</span><span style="color:Black">&nbsp;Payload
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color:Blue">from</span><span style="color:Black">&nbsp;FifoQueue&nbsp;</span><span style="color:Blue">with</span><span style="color:Black">&nbsp;</span><span style="color:Gray">(</span><span style="color:Blue">rowlock</span><span style="color:Gray">,</span><span style="color:Black">&nbsp;</span><span style="color:Blue">readpast</span><span style="color:Gray">)
</span><span style="color:Black">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color:Blue">order</span><span style="color:Black">&nbsp;</span><span style="color:Blue">by</span><span style="color:Black">&nbsp;Id</span><span style="color:Blue">&nbsp;DESC</span><span style="color:Gray">)
</span><span style="color:Black">&nbsp;&nbsp;</span><span style="color:Blue">delete</span><span style="color:Black">&nbsp;</span><span style="color:Blue">from</span><span style="color:Black">&nbsp;cte
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color:Blue">output</span><span style="color:Black">&nbsp;deleted</span><span style="color:Gray">.</span><span style="color:Black">Payload</span><span style="color:Gray">;
</span>
</pre>
<p></code></p>
<p>Because all operations (enqueue and dequeue) occur on the same rows, stacks implemented as tables tend to create a very hot spot on the page which currently contains these rows. Because all row insert, delete and update operations need to lock the page latch exclusively and stacks  operate on the rows grouped at one end of the table, the result is high page latch contention on this page. Queues have the same problem, but to a lesser extent as the operations are spread in inserts at one end of the table and deletes at the other end, so the same number of operations is split into two hot spots instead of a single one like in stacks case.</p>
<h2><a name="PendingQueues">Pending Queues</a></h2>
<p>Another category of queues are pending queues. Items are inserted with a due date, and the dequeue operation returns rows that are due at dequeue time. This type of queues is common in scheduling systems.</p>
<p><code>
<pre>
<span style="color: Black"></span><span style="color:Blue">create</span><span style="color:Black">&nbsp;</span><span style="color:Blue">table</span><span style="color:Black">&nbsp;PendingQueue&nbsp;</span><span style="color:Gray">(
</span><span style="color:Black">&nbsp;&nbsp;DueTime&nbsp;</span><span style="color:Blue">datetime</span><span style="color:Black">&nbsp;</span><span style="color:Gray">not</span><span style="color:Black">&nbsp;</span><span style="color:Gray">null,
</span><span style="color:Black">&nbsp;&nbsp;Payload&nbsp;</span><span style="color:Blue">varbinary</span><span style="color:Gray">(</span><span style="color:Fuchsia">max</span><span style="color:Gray">));

</span><span style="color:Blue">create</span><span style="color:Black">&nbsp;</span><span style="color:Blue">clustered</span><span style="color:Black">&nbsp;</span><span style="color:Blue">index</span><span style="color:Black">&nbsp;cdxPendingQueue&nbsp;</span><span style="color:Blue">on</span><span style="color:Black">&nbsp;PendingQueue&nbsp;</span><span style="color:Gray">(</span><span style="color:Black">DueTime</span><span style="color:Gray">);
</span><span style="color:Black">go

</span><span style="color:Blue">create</span><span style="color:Black">&nbsp;</span><span style="color:Blue">procedure</span><span style="color:Black">&nbsp;usp_enqueuePending
&nbsp;&nbsp;@dueTime&nbsp;</span><span style="color:Blue">datetime</span><span style="color:Gray">,
</span><span style="color:Black">&nbsp;&nbsp;@payload&nbsp;</span><span style="color:Blue">varbinary</span><span style="color:Gray">(</span><span style="color:Fuchsia">max</span><span style="color:Gray">)
</span><span style="color:Blue">as
</span><span style="color:Black">&nbsp;&nbsp;</span><span style="color:Blue">set</span><span style="color:Black">&nbsp;</span><span style="color:Blue">nocount</span><span style="color:Black">&nbsp;</span><span style="color:Blue">on</span><span style="color:Gray">;
</span><span style="color:Black">&nbsp;&nbsp;</span><span style="color:Blue">insert</span><span style="color:Black">&nbsp;</span><span style="color:Blue">into</span><span style="color:Black">&nbsp;PendingQueue&nbsp;</span><span style="color:Gray">(</span><span style="color:Black">DueTime</span><span style="color:Gray">,</span><span style="color:Black">&nbsp;Payload</span><span style="color:Gray">)
</span><span style="color:Black">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color:Blue">values</span><span style="color:Black">&nbsp;</span><span style="color:Gray">(</span><span style="color:Black">@dueTime</span><span style="color:Gray">,</span><span style="color:Black">&nbsp;@payload</span><span style="color:Gray">);
</span><span style="color:Black">go

</span><span style="color:Blue">create</span><span style="color:Black">&nbsp;</span><span style="color:Blue">procedure</span><span style="color:Black">&nbsp;usp_dequeuePending
</span><span style="color:Blue">as
</span><span style="color:Black">&nbsp;&nbsp;</span><span style="color:Blue">set</span><span style="color:Black">&nbsp;</span><span style="color:Blue">nocount</span><span style="color:Black">&nbsp;</span><span style="color:Blue">on</span><span style="color:Gray">;
</span><span style="color:Black">&nbsp;&nbsp;</span><span style="color:Blue">declare</span><span style="color:Black">&nbsp;@now&nbsp;</span><span style="color:Blue">datetime</span><span style="color:Gray">;
</span><span style="color:Black">&nbsp;&nbsp;</span><span style="color:Blue">set</span><span style="color:Black">&nbsp;@now&nbsp;</span><span style="color:Gray">=</span><span style="color:Black">&nbsp;</span><span style="color:Fuchsia">getutcdate</span><span style="color:Gray">();
</span><span style="color:Black">&nbsp;&nbsp;</span><span style="color:Blue">with</span><span style="color:Black">&nbsp;cte&nbsp;</span><span style="color:Blue">as</span><span style="color:Black">&nbsp;</span><span style="color:Gray">(
</span><span style="color:Black">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color:Blue">select</span><span style="color:Black">&nbsp;</span><span style="color:Blue">top</span><span style="color:Gray">(</span><span style="color:Black">1</span><span style="color:Gray">)</span><span style="color:Black">&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Payload
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color:Blue">from</span><span style="color:Black">&nbsp;PendingQueue&nbsp;</span><span style="color:Blue">with</span><span style="color:Black">&nbsp;</span><span style="color:Gray">(</span><span style="color:Blue">rowlock</span><span style="color:Gray">,</span><span style="color:Black">&nbsp;</span><span style="color:Blue">readpast</span><span style="color:Gray">)
</span><span style="color:Black">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color:Blue">where</span><span style="color:Black">&nbsp;DueTime&nbsp;</span><span style="color:Gray">&lt;</span><span style="color:Black">&nbsp;@now
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color:Blue">order</span><span style="color:Black">&nbsp;</span><span style="color:Blue">by</span><span style="color:Black">&nbsp;DueTime</span><span style="color:Gray">)
</span><span style="color:Black">&nbsp;&nbsp;</span><span style="color:Blue">delete</span><span style="color:Black">&nbsp;</span><span style="color:Blue">from</span><span style="color:Black">&nbsp;cte
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color:Blue">output</span><span style="color:Black">&nbsp;deleted</span><span style="color:Gray">.</span><span style="color:Black">Payload</span><span style="color:Gray">;
</span><span style="color:Black">go
</span>
</pre>
<p></code></p>
<p>I choose to use UTC times for my example, and I highly recommend you do the same for your applications. Not only this eliminates the problem of having to deal with timezones, but also your pending operations will behave correctly on the two times each year when summer time enters into effect or when it ends.</p>
<h3>Why not use built-in Queues?</h3>
<p>SQL Server has Queues, right? After all, what else are statements like CREATE QUEUE and DROP QUEUE refer to? Well, not really. SQL Server includes Service Broker, it&#8217;s true, and Service Broker uses these message stores that, for lack of a better term, where called Queues. But even during product development serious consideration was given to whether a different term should be used instead of &#8216;queue&#8217; (eg. use &#8216;message store&#8217;). In the end the decision was made to use the term &#8216;queue&#8217; given the industry familiarity with the term. But make no mistake, Service Broker &#8216;queues&#8217; are not a generic queue storage for anyone to use. They are intended solely as a store of messages for Service Broker. If you try to use them as a generic queue, several shortcomings will become immediately apparent:</p>
<ul>
<li>Difficulty to enqueue. With Service Broker Queues you need to begin a conversation and send a message on it in order to enqueue something into a queue. What is a conversation you ask? My point exactly: the semantics exposed by Service Broker are those needed for it&#8217;s purpose, namely reliable messaging. You do not need to learn about services, contracts, message types, routes and remote service bindings <i>just to enqueue a row into a queue</i>.</li>
<li>Fixed structure. Service Broker Queues have a specific table structure that cannot be altered in any fashion. You cannot add, alter or drop columns, you cannot change the indexes, you cannot change the clustered index. The Service Broker queues schema is designed for the RECEIVE verb and for the <a href="http://msdn.microsoft.com/en-us/library/ms171615.aspx" target="_blank">conversation group locking</a> semantics of Service Broker, but that schema may not be what is optimal for your case.</li>
<li>Lack of maintenance options. I blogged about this issue in my article <a href="http://rusanu.com/2010/03/09/dealing-with-large-queues/">Dealing with Large Queues</a>. With Service Broker Queues you cannot use any of the table maintenance DDL, like rebuilding or reorganizing an index, you cannot use DMVs like <a href="http://msdn.microsoft.com/en-us/library/ms188917.aspx" target="_blank">sys.dm_db_index_physical_stats</a> nor can you change the various table options via <a href="http://msdn.microsoft.com/en-us/library/ms173530.aspx" target="_blank">sp_tableoptions</a>.</li>
</ul>
<p>However Service Broker has one ace up its selves: <b><a href="http://msdn.microsoft.com/en-us/library/ms171617.aspx" target="_blank">Activation</a></b>. Queue processing is often associated with event driven programming and the possibility to launch a procedure to handle incoming rows as they are enqueued in is always required with queues. Triggers don&#8217;t work as processing has to occur after the enqueue is committed. And scheduled SQL Agent jobs don&#8217;t adapt to the variable rates and spikes queue experience: if they are too aggressive they&#8217;ll burn CPU, but if they are too passive the latency increases even under no load. Is hard enough to tune it for a sweet spot under a constant load, but add a variable load with spikes and the task becomes impossible. Unfortunately there is no substitute for Activation, you have to handle the processing as a separate tasks that polls the queue for new rows. The only way to leverage activation, with it&#8217;s sweet mix of non-polling and self load balancing, is to use Service Broker Queues.</p>
]]></content:encoded>
			<wfw:commentRss>http://rusanu.com/2010/03/26/using-tables-as-queues/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
