<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Henk's  tech blog</title>
	
	<link>http://henkvandervalk.com</link>
	<description>a weblog about IT optimization</description>
	<lastBuildDate>Sat, 25 Feb 2012 19:34:06 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/HenksTechBlog" /><feedburner:info uri="henkstechblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>SQL under the hood (Part 2): Estimate the SQL Disk IO Workload based on the Virtual File Stats DMV.</title>
		<link>http://feedproxy.google.com/~r/HenksTechBlog/~3/ar4eGG8t27Q/sql-under-the-hood-part-2-estimate-the-sql-disk-io-workload-based-on-the-virtual-file-stats-dmv</link>
		<comments>http://henkvandervalk.com/sql-under-the-hood-part-2-estimate-the-sql-disk-io-workload-based-on-the-virtual-file-stats-dmv#comments</comments>
		<pubDate>Fri, 20 Jan 2012 20:59:29 +0000</pubDate>
		<dc:creator>Henk</dc:creator>
				<category><![CDATA[SQL 2008 R2]]></category>
		<category><![CDATA[Workload & Capacity Planning]]></category>
		<category><![CDATA[Optimization]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[VFS]]></category>
		<category><![CDATA[Virtual File Stats]]></category>

		<guid isPermaLink="false">http://henkvandervalk.com/?p=682</guid>
		<description><![CDATA[Do you know how much data is being written and read on a daily basis by your SQL Server databases? SQL Server keeps track of these stats for you already; you just have to retrieve and interpret them correctly so you can turn this data into valuable information. A couple of years ago I was [...]]]></description>
				<content:encoded><![CDATA[<p>Do you know how much data is being written and read on a daily basis by your SQL Server databases? SQL Server keeps track of these stats for you already; you just have to retrieve and interpret them correctly so you can turn this data into valuable information.</p>
<p>A couple of years ago I was looking for a way to quickly quantify the overall SQL workload of a server that I never had seen before and noticed the beauty of the sys.dm_io_virtual_file_stats DMV. This DMV returns the I/O statistics for each SQL database; for both the data- and the log files collected since an SQL Server instance has been started. You can take a rough ‘guestimate’&#160; about how much data physically is being touched and processed by you disk subsystem if you divide these numbers by the uptime of the SQL instance and turn them into a metric you prefer;&#160; bytes per second or Gigabytes processed per day. </p>
<h3>The VFS Query</h3>
<p>Every step in the query below is documented and self-explanatory; it just queries sys.databases to figure out when the SQL instance started, the sys.dm_io_virtual_file_stats DMV. </p>
<pre style="width: 654px; height: 888px" class="code"><span style="color: green">--------------------------------------------------------------------------------------------
--  Script to snapshot the SQL SMP Virtual Filestats  and calculate and average per day 
--  based on the SQL instance uptime (calc. in seconds)
--  V1.1 by Henk van der Valk    Script provided 'as-is'
--------------------------------------------------------------------------------------------
</span><span style="color: blue">USE master
go

SET NOCOUNT ON
DECLARE </span>@crDate <span style="color: blue">DateTime</span><span style="color: gray">; 
</span><span style="color: blue">DECLARE </span>@hours <span style="color: blue">DECIMAL</span><span style="color: gray">(</span>18<span style="color: gray">,</span>3<span style="color: gray">), </span>@Days <span style="color: blue">int</span><span style="color: gray">;
</span><span style="color: blue">DECLARE </span>@FinalHours <span style="color: blue">int</span><span style="color: gray">, </span>@FinalMinutes <span style="color: blue">int</span><span style="color: gray">, </span>@FinalSeconds <span style="color: blue">int</span><span style="color: gray">, </span>@total_seconds  <span style="color: blue">int</span><span style="color: gray">;


</span><span style="color: green">-- Determine uptime by checking Tempdb creation datetime:
</span><span style="color: blue">SELECT top </span>1 @crdate<span style="color: gray">=</span>create_date <span style="color: blue">FROM </span><span style="color: green">sys</span><span style="color: gray">.</span><span style="color: green">databases </span><span style="color: blue">WHERE </span>NAME<span style="color: gray">=</span><span style="color: red">'tempdb'
</span><span style="color: blue">SELECT </span>@hours <span style="color: gray">= </span><span style="color: magenta">DATEDIFF</span><span style="color: gray">(</span>ss<span style="color: gray">,</span>@crDate<span style="color: gray">,</span><span style="color: magenta">GETDATE</span><span style="color: gray">())/</span><span style="color: magenta">CAST</span><span style="color: gray">(</span>60 <span style="color: blue">AS Decimal</span><span style="color: gray">)/</span><span style="color: magenta">CAST</span><span style="color: gray">(</span>60 <span style="color: blue">AS Decimal</span><span style="color: gray">);
</span><span style="color: blue">PRINT </span><span style="color: red">'SQL Server instance '</span><span style="color: gray">+ </span><span style="color: magenta">@@SERVERNAME </span><span style="color: gray">+ </span><span style="color: red">'\' </span><span style="color: gray">+ </span><span style="color: magenta">@@SERVICENAME </span><span style="color: gray">+ </span><span style="color: red">' is Up since: ' </span><span style="color: gray">+ </span><span style="color: magenta">CAST </span><span style="color: gray">(</span>@crdate <span style="color: blue">as varchar</span><span style="color: gray">)  ;

</span><span style="color: green">-- From hours to days:
</span><span style="color: blue">SELECT </span>@Days <span style="color: gray">= </span>@hours<span style="color: gray">/</span><span style="color: magenta">CAST</span><span style="color: gray">(</span>24 <span style="color: blue">AS Decimal</span><span style="color: gray">);

</span><span style="color: green">-- Determine the remaining part of the hours: 
</span><span style="color: blue">SELECT </span>@FinalHours <span style="color: gray">= </span>@hours <span style="color: gray">- (</span>@Days<span style="color: gray">*</span><span style="color: magenta">CAST</span><span style="color: gray">(</span>24 <span style="color: blue">AS Decimal</span><span style="color: gray">))

</span><span style="color: green">-- Remaining minutes: 
</span><span style="color: blue">SELECT </span>@FinalMinutes <span style="color: gray">= (</span>@hours <span style="color: gray">- (</span>@Days<span style="color: gray">*</span><span style="color: magenta">CAST</span><span style="color: gray">(</span>24 <span style="color: blue">AS Decimal</span><span style="color: gray">)) - </span>@FinalHours <span style="color: gray">) * </span>60<span style="color: gray">;

</span><span style="color: green">-- Remaining seconds: 
</span><span style="color: blue">SELECT </span>@FinalSeconds <span style="color: gray">= (((</span>@hours <span style="color: gray">- (</span>@Days<span style="color: gray">*</span><span style="color: magenta">CAST</span><span style="color: gray">(</span>24 <span style="color: blue">AS Decimal</span><span style="color: gray">)) - </span>@FinalHours <span style="color: gray">) * </span>60<span style="color: gray">) - </span>@Finalminutes<span style="color: gray">) * </span>60<span style="color: gray">;

</span><span style="color: blue">PRINT </span><span style="color: red">'Or: '</span><span style="color: gray">+ </span><span style="color: magenta">CAST</span><span style="color: gray">(</span>@Days <span style="color: blue">as varchar</span><span style="color: gray">) + </span><span style="color: red">' Days, ' </span><span style="color: gray">+ </span><span style="color: magenta">CAST</span><span style="color: gray">(</span>@FinalHours <span style="color: blue">as varchar</span><span style="color: gray">) + </span><span style="color: red">' Hours,'
</span><span style="color: gray">+ </span><span style="color: magenta">CAST</span><span style="color: gray">(</span>@FinalMinutes <span style="color: blue">as varchar</span><span style="color: gray">) + </span><span style="color: red">' Minutes and ' </span><span style="color: gray">+  </span><span style="color: magenta">CAST</span><span style="color: gray">(</span>@FinalSeconds <span style="color: blue">as varchar</span><span style="color: gray">) + </span><span style="color: red">' Seconds.'

</span><span style="color: blue">SELECT  </span>@total_seconds <span style="color: gray">= (</span><span style="color: magenta">CAST</span><span style="color: gray">(</span>@Days <span style="color: blue">AS decimal</span><span style="color: gray">(</span>12<span style="color: gray">,</span>2<span style="color: gray">))*</span>24<span style="color: gray">*</span>3600 <span style="color: gray">+ </span><span style="color: magenta">CAST</span><span style="color: gray">(</span>@Finalhours <span style="color: blue">AS decimal</span><span style="color: gray">(</span>12<span style="color: gray">,</span>2<span style="color: gray">))*</span>3600 <span style="color: gray">+ </span><span style="color: magenta">CAST</span><span style="color: gray">(</span>@Finalminutes <span style="color: blue">AS decimal</span><span style="color: gray">(</span>12<span style="color: gray">,</span>2<span style="color: gray">))*</span>60 <span style="color: gray">)
+ </span><span style="color: magenta">CAST</span><span style="color: gray">(</span>@Finalseconds <span style="color: blue">AS decimal</span><span style="color: gray">(</span>12<span style="color: gray">,</span>2<span style="color: gray">))
</span><span style="color: blue">PRINT </span><span style="color: red">'Total uptime in seconds: '</span><span style="color: gray">+ </span><span style="color: magenta">CONVERT</span><span style="color: gray">(</span><span style="color: blue">VARCHAR</span><span style="color: gray">(</span>20<span style="color: gray">) ,</span>@total_seconds <span style="color: gray">)

</span><span style="color: blue">SELECT </span><span style="color: magenta">@@SERVERNAME </span><span style="color: blue">as </span>Hostname<span style="color: gray">, </span><span style="color: magenta">@@SERVICENAME </span><span style="color: blue">as </span>Instancename<span style="color: gray">, </span>@crdate <span style="color: blue">AS </span>SQL_Start_Date_Time <span style="color: gray">,  </span>@total_seconds <span style="color: blue">as </span>TotalSeconds_Up

<span style="color: blue">SELECT  </span><span style="color: magenta">DB_NAME</span><span style="color: gray">(</span>database_id<span style="color: gray">) </span><span style="color: blue">AS </span>[Database Name] <span style="color: gray">,
        </span><span style="color: magenta">file_id </span><span style="color: gray">,
        </span>io_stall_read_ms <span style="color: gray">,
        </span>num_of_reads <span style="color: gray">,
            (</span>num_of_bytes_read <span style="color: gray">/ </span>1024 <span style="color: gray">/ </span>1024 <span style="color: gray">/</span>1024<span style="color: gray">) </span><span style="color: blue">as </span>GB_Read_Total<span style="color: gray">,
            </span>num_of_bytes_read <span style="color: gray">/ </span>@total_seconds <span style="color: gray">* </span>3600 <span style="color: gray">* </span>24 <span style="color: gray">/</span>1024<span style="color: gray">/</span>1024<span style="color: gray">/</span>1024  <span style="color: blue">as </span>AVG_GB_read_per_day_ESTIMATE<span style="color: gray">,
        </span><span style="color: magenta">CAST</span><span style="color: gray">(</span>io_stall_read_ms <span style="color: gray">/ ( </span>1.0 <span style="color: gray">+ </span>num_of_reads <span style="color: gray">) </span><span style="color: blue">AS NUMERIC</span><span style="color: gray">(</span>10<span style="color: gray">, </span>1<span style="color: gray">))
            </span><span style="color: blue">AS </span>[avg_read_stall_ms] <span style="color: gray">,
        </span>io_stall_write_ms <span style="color: gray">,
        </span>num_of_writes <span style="color: gray">,
            </span>num_of_bytes_written <span style="color: gray">/ </span>1024 <span style="color: gray">/ </span>1024<span style="color: gray">/</span>1024 <span style="color: blue">as </span>GB_Written_Total<span style="color: gray">,
            </span>num_of_bytes_written <span style="color: gray">/</span>@total_seconds <span style="color: gray">* </span>3600 <span style="color: gray">* </span>24 <span style="color: gray">/</span>1024<span style="color: gray">/</span>1024<span style="color: gray">/</span>1024  <span style="color: blue">as </span>AVG_GB_Written_per_day_ESTIMATE<span style="color: gray">,
        </span><span style="color: magenta">CAST</span><span style="color: gray">(</span>io_stall_write_ms <span style="color: gray">/ ( </span>1.0 <span style="color: gray">+ </span>num_of_writes <span style="color: gray">) </span><span style="color: blue">AS NUMERIC</span><span style="color: gray">(</span>10<span style="color: gray">, </span>1<span style="color: gray">))
            </span><span style="color: blue">AS </span>[avg_write_stall_ms] <span style="color: gray">,
        </span>io_stall_read_ms <span style="color: gray">+ </span>io_stall_write_ms <span style="color: blue">AS </span>[IO_Stalls] <span style="color: gray">,
        </span>num_of_reads <span style="color: gray">+ </span>num_of_writes <span style="color: blue">AS </span>[Total_IO] <span style="color: gray">,
        </span><span style="color: magenta">CAST</span><span style="color: gray">(( </span>io_stall_read_ms <span style="color: gray">+ </span>io_stall_write_ms <span style="color: gray">) / ( </span>1.0 <span style="color: gray">+ </span>num_of_reads
                                                          <span style="color: gray">+ </span>num_of_writes<span style="color: gray">)
           </span><span style="color: blue">AS NUMERIC</span><span style="color: gray">(</span>10<span style="color: gray">,</span>1<span style="color: gray">)) </span><span style="color: blue">AS </span>[AVG_IO_stall_ms]
<span style="color: blue">FROM    </span><span style="color: green">sys</span><span style="color: gray">.</span><span style="color: green">dm_io_virtual_file_stats</span><span style="color: gray">(NULL, NULL)
</span><span style="color: green">--ORDER BY avg_io_stall_ms DESC ;
</span><span style="color: blue">order by </span>GB_read_total <span style="color: blue">DESC


</span></pre>
<h3>Sample VFS Query output</h3>
<p>The output example below shows the regular VFS output with some additional columns to quantify the workload; for each database file it shows the Gigabytes_Read_Total since start, the Average_Gigabytes_Read_per_Day, assuming a 24&#215;7 operation, the average_read_stall_milliseconds that users have waited for reads issued on a file, and similar columns for the write stats.&#160; </p>
<p>Don’t be surprised when the tempdb traffic is by far the largest Disk IO consumer or when an unbalance between database files and stall timings show.&#160; This could be a good place to start monitoring the effective IO response timings of the LUNS you have available and if they cope well or that you are suffering from some hotspots.</p>
<p><a href="http://henkvandervalk.com/wp-content/uploads/2012/01/image2.png" rel="lightbox[682]" title="VFS output"><img style="display: inline" title="VFS output" alt="Estimate the GBytes processed by SQL Server" src="http://henkvandervalk.com/wp-content/uploads/2012/01/image_thumb2.png" width="679" height="133" /></a></p>
<p>&#160;</p>
<h3>Wrap up</h3>
<p>The information provided by the sys.dm_io_virtual_file_stats DMV will help you to quantify the daily Disk IO workload of your SQL Servers. When you store the results, over time, it will also show you if the overall usage of your SQL environment increases. </p>
<p>I’ve seen VFS stats of production databases who are reading on average 6-19 Terabyte/day. When you update more than 1 TB+/day on your main production databases, please shoot me a mail ; your workload very likely qualifies for SQL Server Parallel Data Warehouse! </p>
<img src="http://feeds.feedburner.com/~r/HenksTechBlog/~4/ar4eGG8t27Q" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://henkvandervalk.com/sql-under-the-hood-part-2-estimate-the-sql-disk-io-workload-based-on-the-virtual-file-stats-dmv/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://henkvandervalk.com/sql-under-the-hood-part-2-estimate-the-sql-disk-io-workload-based-on-the-virtual-file-stats-dmv</feedburner:origLink></item>
		<item>
		<title>SQL Server Days 2011</title>
		<link>http://feedproxy.google.com/~r/HenksTechBlog/~3/jkBkKiqntec/sql-server-days-2011</link>
		<comments>http://henkvandervalk.com/sql-server-days-2011#comments</comments>
		<pubDate>Wed, 09 Nov 2011 22:40:38 +0000</pubDate>
		<dc:creator>Henk</dc:creator>
				<category><![CDATA[Events]]></category>
		<category><![CDATA[SQL2008R2 Parallel Data Warehouse]]></category>

		<guid isPermaLink="false">http://henkvandervalk.com/sql-server-days-2011</guid>
		<description><![CDATA[Please join me at the Belgian SQL Server Days on November 14 &#38; 15!&#160; I will be presenting on Monday about SQL PDW.]]></description>
				<content:encoded><![CDATA[<p>Please join me at the Belgian SQL Server Days on November 14 &amp; 15!&#160; </p>
<p>I will be presenting on Monday about SQL PDW.</p>
<p><a title="PDW session coming up at the SQL Server Days 2011" href="http://www.sqlserverdays.be/?page_id=17#HVDV_Session1" target="_blank"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://henkvandervalk.com/wp-content/uploads/2011/11/image2.png" width="366" height="199" /></a></p>
<p><a title="Register here!" href="http://www.sqlserverdays.be/?page_id=6" target="_blank"><img src="http://www.sqlserverdays.be/wp-content/uploads/2011/09/SQLServerDays2011.gif" /></a></p>
<img src="http://feeds.feedburner.com/~r/HenksTechBlog/~4/jkBkKiqntec" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://henkvandervalk.com/sql-server-days-2011/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://henkvandervalk.com/sql-server-days-2011</feedburner:origLink></item>
		<item>
		<title>SQL2008 R2 DCE on a 96 core Unisys ES7000 server with DSI Solid State storage: Bulk Inserting 1 Terabyte within 10 minutes</title>
		<link>http://feedproxy.google.com/~r/HenksTechBlog/~3/En6ixxWfa10/sql2008-r2-dce-on-a-96-core-unisys-es7000-server-with-dsi-solid-state-storage-bulk-inserting-1-terabyte-within-10-minutes</link>
		<comments>http://henkvandervalk.com/sql2008-r2-dce-on-a-96-core-unisys-es7000-server-with-dsi-solid-state-storage-bulk-inserting-1-terabyte-within-10-minutes#comments</comments>
		<pubDate>Mon, 23 Aug 2010 20:10:50 +0000</pubDate>
		<dc:creator>Henk</dc:creator>
				<category><![CDATA[SQL 2008 R2]]></category>
		<category><![CDATA[Storage: SAN & SSD]]></category>
		<category><![CDATA[Windows 2008 R2]]></category>
		<category><![CDATA[Bulk Insert]]></category>
		<category><![CDATA[Solid State]]></category>
		<category><![CDATA[SQL2008R2]]></category>
		<category><![CDATA[SSD]]></category>

		<guid isPermaLink="false">http://henkvandervalk.com/?p=617</guid>
		<description><![CDATA[Hopefully you have seen the high-speed data loading demo live over the last 1.5 years at some SQL Server conference? I remember demoing it the first time –live- with Thomas Kejser at the European SQLPass 2009 conference during the opening keynote to show the 64+ Core support in SQL2008 R2. But for those of you [...]]]></description>
				<content:encoded><![CDATA[<p>Hopefully you have seen the high-speed data loading demo live over the last 1.5 years at some SQL Server conference? I remember demoing it the first time –live- with Thomas <a href="http://www.kejser.org/" target="_blank">Kejser</a> at the European SQLPass 2009 conference during the opening keynote to show the 64+ Core support in SQL2008 R2. But for those of you who haven’t, hereby an impression of what data loading throughput you can achieve on a 96 core Unisys <a href="http://www.app3.unisys.com/7600R/index.html" target="_blank">ES7000 Server</a> with 2 <a href="http://www.dynamicsolutions.com/dsi3600" target="_blank">DSI</a> Solid State units attached (which we codenamed the <a href="http://www.sqlpowerrack.com/" target="_blank">SQL Powerrack</a>); it’s running 3 times faster than our SQL 2008 <a href="http://msdn.microsoft.com/en-us/library/dd537533.aspx" target="_blank">ETL World Record</a> of 1 TB within 30 minutes. A small movie tells you more than a thousand words, so watch how 96 flat files are being bulk inserted simultaneous into a single SQL database and read also how to get maximum speed out of bulk inserting yourselves.</p>
</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:bff6f2cf-d852-4739-8e6b-78bca32139c7" class="wlWriterEditableSmartContent">
<div><object width="425" height="355"><param name="movie" value="http://www.youtube.com/v/oz9XqFTTo1k&amp;hl=en"></param><embed src="http://www.youtube.com/v/oz9XqFTTo1k&amp;hl=en" type="application/x-shockwave-flash" width="425" height="355"></embed></object></div>
<div style="clear:both;font-size:.8em;">96 parallel Bulk Inserts @ work</div>
</div>
<p><a href="http://henkvandervalk.com/wp-content/uploads/2010/08/image161.png" rel="lightbox[617]" title="All you need: the SQL Powerrack with an 4 cell ES7000 and only 2 DSI SSD (2U high) shelves."><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="All you need: the SQL Powerrack with an 4 cell ES7000 and only 2 DSI SSD (2U high) shelves." border="0" alt="All you need: the SQL Powerrack with an 4 cell ES7000 and only 2 DSI SSD (2U high) shelves." src="http://henkvandervalk.com/wp-content/uploads/2010/08/image16_thumb.png" width="145" height="384" /></a>&#160;&#160; <a href="http://henkvandervalk.com/wp-content/uploads/2010/08/image191.png" rel="lightbox[617]" title="Thomas Kejser and I at the SQLPass  2009 European Conference; big numbers  on a big screen!"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Thomas Kejser and I at the SQLPass  2009 European Conference; big numbers  on a big screen!" border="0" alt="Thomas Kejser and I at the SQLPass  2009 European Conference; big numbers  on a big screen!" src="http://henkvandervalk.com/wp-content/uploads/2010/08/image19_thumb.png" width="463" height="383" /></a> </p>
<h3>SQL2008 R2 Datacenter Edition</h3>
<p>With the official RTM build of SQL Server 2008 R2 Data Center Edition the overall throughput is even slightly higher than the CTP1 version that we used at the <a href="http://www.sqlpass.org/summit/eu2010/" target="_blank">European Pass (2009) conference</a>; imagine… bulk inserting over 16 million LineItem rows/sec with 16 columns of data each…&#160; (16 million…that’s roughly the number of citizens over here in the Netherlands..)</p>
<p>Reading the 96 flatfiles with a sustained read speed over 2000 MB/sec and inserting it into the database with over 1700 MB/sec… definitely some numbers to remember!</p>
<p><a href="http://henkvandervalk.com/wp-content/uploads/2010/08/image411.png"></a></p>
<p><a href="http://henkvandervalk.com/wp-content/uploads/2010/08/image91.png" rel="lightbox[617]" title="Bulk Inserting  16 million rows/sec"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Bulk Inserting  16 million rows/sec" border="0" alt="Bulk Inserting  16 million rows/sec" src="http://henkvandervalk.com/wp-content/uploads/2010/08/image9_thumb.png" width="620" height="372" /></a></p>
<p>The Windows Task Manager looks like this when starting all 96 tasks at the same time:</p>
<p><a href="http://henkvandervalk.com/wp-content/uploads/2010/08/image412.png" rel="lightbox[617]" title="Fireing up 96 Bulk Insert tasks in Parallel, each on its own core."><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Fireing up 96 Bulk Insert tasks in Parallel, each on its own core." border="0" alt="Fireing up 96 Bulk Insert tasks in Parallel, each on its own core." src="http://henkvandervalk.com/wp-content/uploads/2010/08/image4_thumb1.png" width="626" height="375" /></a>&#160;</p>
<h3>Optimizations</h3>
<p>With the incredible fast Solid State storage units from <a href="http://www.dynamicsolutions.com/main-menu/solid-state-disk" target="_blank">DSI</a> hooked up to our 96 core Unisys ES7000 server very little tuning is needed to achieve these throughput numbers; </p>
<p>the only 3 things to take care of are:</p>
<p>1) Configure multiple Windows LUN’s on the SSD devices. (With MPIO enabled at approx. 140000 IOPS a LUN&#160; gets saturated).</p>
<p>2) Use 96 database files/24 Filegroups to prevent PFS contention becoming a bottleneck</p>
<p>3) Use the “Harakiri” Stored Procedure to check that only 1 Bulk Insert task gets assigned to each SQL Scheduler.</p>
<p>&#160;</p>
<h3>The SQLPowerrack @ Work</h3>
<p>I was reading through my old notes from the SQL2008 ETL World Record and noticed that we ran with 56 parallel streams, each writing out the heavy-weight LineItem file data with approx. 10-12 MB/sec. Currently, with SQL2008R2, the write speed is up to 54-58 MB/sec per stream with 96 parallel streams. Quite a difference I would say!&#160; Also the disk write IO Response time decreased significantly, from 23-28 milliseconds to 11 milliseconds.</p>
<p><a href="http://henkvandervalk.com/wp-content/uploads/2010/08/image25.png" rel="lightbox[617]" title="Activity Monitor"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Activity Monitor" border="0" alt="Activity Monitor" src="http://henkvandervalk.com/wp-content/uploads/2010/08/image_thumb25.png" width="633" height="160" /></a> </p>
<h3>SQL Waitstats</h3>
<p>When SQL is processing gigabytes of disk IO’s each second it’s worth it to take a snapshot of the sys.dm_os_wait_stats and sys.dm_os_latch_stats DMV to see where SQL is waiting for.</p>
<p>A 1 minute snapshot while running at full speed shows that SQL’s no.1 wait is to read the data from the flat files. With 82% of the wait time. </p>
<p>But, if you calculate the average wait time, you’ll see that it’s waiting for only 0.3 milliseconds for an file access IO while reading sustained 2GB/sec from SSD (and also writing over 1700MB/sec to SSD at the same time) is an amazing value also! </p>
<p><a href="http://henkvandervalk.com/wp-content/uploads/2010/08/image81.png" rel="lightbox[617]" title="1 minute snapshot of the SQL Waitstats;  &quot;waiting&quot; for reading from the flatfiles"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="1 minute snapshot of the SQL Waitstats;  &quot;waiting&quot; for reading from the flatfiles" border="0" alt="1 minute snapshot of the SQL Waitstats;  &quot;waiting&quot; for reading from the flatfiles" src="http://henkvandervalk.com/wp-content/uploads/2010/08/image8_thumb.png" width="635" height="147" /></a></p>
<p>A 1 minute snapshot of the the sys.dm_os_latch_stats show that waits for memory buffer page synchronization requests take on average 1.7 msec.</p>
<p><a href="http://henkvandervalk.com/wp-content/uploads/2010/08/image111.png" rel="lightbox[617]" title="1 minute snapshot of the SQL latch "><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="1 minute snapshot of the SQL latch " border="0" alt="1 minute snapshot of the SQL latch " src="http://henkvandervalk.com/wp-content/uploads/2010/08/image11_thumb.png" width="630" height="38" /></a>&#160;</p>
<h3>The Work Queue</h3>
<p>The Work queue contains primarily a list of all the files that need to be bulk inserted into the database and also its target destination table. Once a task is completed all kind of </p>
<p>statistics, like datetime stamps, duration, IO information, CPU time, CPU/scheduler ID etc., are written into the table also to verify afterwards. (The table definition is listed below).</p>
<p><a href="http://henkvandervalk.com/wp-content/uploads/2010/08/image182.png" rel="lightbox[617]" title="Work Queue content snippet"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Work Queue content snippet" border="0" alt="Work Queue content snippet" src="http://henkvandervalk.com/wp-content/uploads/2010/08/image18_thumb1.png" width="635" height="216" /></a>&#160;</p>
<h3>Preventing Scheduler contention</h3>
<p>Next, basically the only tuning we do is to check if a SQL scheduler is&#160; already allocated to another Bulk Insert task, and if so, to pick another one.    <br />By default, a new session is assigned to any available scheduler in a round robin fashion way, so when for example 2 (or more) Bulk insert tasks reside on the same scheduler, they will stay on that scheduler and have to share the CPU ticks till their both done bulk inserting. This might not be the most effective way to distribute the workload across a multi core server. So if you would prevent this from happening you can apply <a href="http://msdn.microsoft.com/en-us/library/dd537533(SQL.100).aspx" target="_blank">TCP port mapping and soft numa</a> (like we did with the ETL WR) or … keep reading!</p>
<h3>Starting 96 Bulk Inserts at the same time</h3>
<p>For testing purposes, we wrote 2 batch files that allows you to start as many parallel bulk insert tasks as you like (:</p>
<p>For example to start 96 parallel Bulk Inserts, just type: <strong>“Spawnmany Bulk2 96”.</strong></p>
<p>&#160;<a href="http://henkvandervalk.com/wp-content/uploads/2010/08/image26.png" rel="lightbox[617]" title="image"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://henkvandervalk.com/wp-content/uploads/2010/08/image_thumb26.png" width="315" height="244" /></a>&#160; <a href="http://henkvandervalk.com/wp-content/uploads/2010/08/image27.png" rel="lightbox[617]" title="image"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://henkvandervalk.com/wp-content/uploads/2010/08/image_thumb27.png" width="300" height="149" /></a> </p>
<h3>Optimized Bulk Loading routine</h3>
<p>The heart of the bulk loading routine we use is a Stored Procedure that picks a task from a work queue (sp_get_work), checks for a free scheduler and then waits for the “start=1” signal from the Spawnmany.cmd file to continue. Once it’s done with each of the bulk inserting tasks, the session duration and statistics are updated (sp_end_work) and it will check the queue if there’s more work to be done.</p>
<h4>SP Worker_Bulk_Harakiri</h4>
</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:5eba0604-41c3-49d0-adcf-00fd57a6e52d" class="wlWriterEditableSmartContent">
<div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt">
<div style="background-color: #ffffff; max-height: 300px; overflow: auto; padding: 2px 5px; white-space: nowrap"><span style="color:#0000ff">USE</span> [TPCH_1TB]<br /> <span style="color:#0000ff">GO</span></p>
<p> <span style="color:#008000">/****** Object:  StoredProcedure [dbo].[Worker_Bulk_Harakiri] ******/</span><br /> <span style="color:#0000ff">SET</span> <span style="color:#0000ff">ANSI_NULLS</span> <span style="color:#0000ff">ON</span><br /> <span style="color:#0000ff">GO</span></p>
<p> <span style="color:#0000ff">SET</span> <span style="color:#0000ff">QUOTED_IDENTIFIER</span> <span style="color:#0000ff">ON</span><br /> <span style="color:#0000ff">GO</span></p>
<p> <span style="color:#0000ff">CREATE</span> <span style="color:#0000ff">PROCEDURE</span> [dbo]<span style="color:#808080">.</span>[Worker_Bulk_Harakiri]<br /> <span style="color:#0000ff">AS</span><br /> <span style="color:#0000ff">SET</span> <span style="color:#0000ff">NOCOUNT</span> <span style="color:#0000ff">ON</span></p>
<p> <span style="color:#0000ff">DECLARE</span> @my_scheduler <span style="color:#0000ff">INT</span><br /> <span style="color:#0000ff">SELECT</span> @my_scheduler <span style="color:#808080">=</span> scheduler_id<br /> <span style="color:#0000ff">FROM</span> <span style="color:#008000">sys</span><span style="color:#808080">.</span><span style="color:#008000">dm_exec_requests</span><br /> <span style="color:#0000ff">WHERE</span> session_id <span style="color:#808080">=</span> <span style="color:#ff00ff">@@SPID</span></p>
<p> <span style="color:#0000ff">UPDATE</span> scheduler_use <br /> <span style="color:#0000ff">SET</span> session_id <span style="color:#808080">=</span> <span style="color:#ff00ff">@@SPID</span><br /> <span style="color:#0000ff">WHERE</span> session_id <span style="color:#808080">IS</span> <span style="color:#808080">NULL</span> <br /> <span style="color:#808080">AND</span> scheduler_id <span style="color:#808080">=</span> @my_scheduler</p>
<p> <span style="color:#008000">/* We landed on a scheduler that is in use */</span><br /> <span style="color:#0000ff">IF</span> <span style="color:#ff00ff">@@ROWCOUNT</span> <span style="color:#808080">=</span> 0 <span style="color:#0000ff">BEGIN</span><br />     <br /> <span style="color:#0000ff">RAISERROR </span><span style="color:#808080">(</span><span style="color:#ff0000">&#39;Scheduler in use&#39;</span><span style="color:#808080">,</span> 16<span style="color:#808080">,</span> 111<span style="color:#808080">)    </span><br /> <span style="color:#0000ff">RETURN    </span><br /> <span style="color:#0000ff">END</span></p>
<p> <span style="color:#0000ff">DECLARE</span> @start <span style="color:#0000ff">BIT</span> <span style="color:#808080">=</span> 0</p>
<p> <span style="color:#0000ff">WHILE</span> @start <span style="color:#808080">=</span> 0 <span style="color:#0000ff">BEGIN</span></p>
<p>     <span style="color:#0000ff">SELECT</span> @start <span style="color:#808080">=</span> start <span style="color:#0000ff">FROM</span> <span style="color:#0000ff">Control</span><span style="color:#808080">..</span>ready<br />     <span style="color:#0000ff">WAITFOR</span> <span style="color:#0000ff">DELAY</span> <span style="color:#ff0000">&#39;00:00:01&#39;</span><br /> <span style="color:#0000ff">END</span></p>
<p> <span style="color:#0000ff">DECLARE</span> @target <span style="color:#0000ff">NVARCHAR</span><span style="color:#808080">(</span><span style="color:#ff00ff">MAX</span><span style="color:#808080">)</span><br /> <span style="color:#0000ff">DECLARE</span> @assignment <span style="color:#0000ff">NVARCHAR</span><span style="color:#808080">(</span><span style="color:#ff00ff">MAX</span><span style="color:#808080">)</span><br /> <span style="color:#0000ff">DECLARE</span> @partition <span style="color:#0000ff">NVARCHAR</span><span style="color:#808080">(</span><span style="color:#ff00ff">MAX</span><span style="color:#808080">)</span><br /> <span style="color:#0000ff">DECLARE</span> @work_id <span style="color:#0000ff">INT</span> </p>
<p> <span style="color:#0000ff">EXEC</span> [Control]<span style="color:#808080">.</span>dbo<span style="color:#808080">.</span>sp_get_work<span style="color:#0000ff"> </span><span style="color:#ff0000">&#39;BULK&#39;</span><br />     <span style="color:#808080">,</span> @work_id <span style="color:#0000ff">OUTPUT</span><span style="color:#808080">,</span> @assignment <span style="color:#0000ff">OUTPUT</span><span style="color:#808080">,</span> @target <span style="color:#0000ff">OUTPUT</span></p>
<p> <span style="color:#0000ff">WHILE</span> @work_id <span style="color:#808080">IS</span> <span style="color:#808080">NOT</span> <span style="color:#808080">NULL</span> <span style="color:#0000ff">BEGIN</span></p>
<p>     <span style="color:#0000ff">DECLARE</span> @sql <span style="color:#0000ff">NVARCHAR</span><span style="color:#808080">(</span>4000<span style="color:#808080">)</span></p>
<p>     <span style="color:#0000ff">PRINT</span> @target<br />     <span style="color:#0000ff">PRINT</span> @assignment</p>
<p>     <span style="color:#0000ff">SET</span> @sql <span style="color:#808080">=</span> <span style="color:#ff0000">&#39;BULK INSERT &#39;</span> <span style="color:#808080">+</span> @target<br />         <span style="color:#808080">+</span> <span style="color:#ff0000">&#39; FROM &#39;&#39;&#39;</span> <span style="color:#808080">+</span> @assignment <span style="color:#808080">+</span> <span style="color:#ff0000">&#39;&#39;&#39;&#39;</span><br />         <span style="color:#808080">+</span> <span style="color:#ff0000">&#39; WITH (</span><br /> <span style="color:#ff0000">         CODEPAGE = &#39;&#39;OEM&#39;&#39;, DATAFILETYPE = &#39;&#39;CHAR&#39;&#39;, TABLOCK&#39;</span><br />         <span style="color:#808080">+</span> <span style="color:#ff0000">&#39;, ROWTERMINATOR =&#39;&#39;|&#92;n&#39;&#39;, FIELDTERMINATOR = &#39;&#39;|&#39;&#39;)&#39;</span></p>
<p>     <span style="color:#0000ff">RAISERROR </span><span style="color:#808080">(</span>@sql<span style="color:#808080">,</span> 10<span style="color:#808080">,</span> 1<span style="color:#808080">)</span> <span style="color:#0000ff">WITH</span> <span style="color:#0000ff">NOWAIT    </span><span style="color:#008000">/* print the message immediately */</span><br />     <span style="color:#0000ff">EXEC</span> <span style="color:#800000">sp_executesql</span><span style="color:#0000ff"> </span>@sql<br />     <span style="color:#0000ff">IF</span> <span style="color:#ff00ff">@@ERROR</span> <span style="color:#808080">&lt;&gt;</span> 0 <span style="color:#0000ff">BEGIN</span><br />         <span style="color:#0000ff">RETURN    </span><span style="color:#008000">/* Do not mark he work as ended if error occurred */</span><br />     <span style="color:#0000ff">END</span></p>
<p>     <span style="color:#0000ff">EXEC</span> [Control]<span style="color:#808080">.</span>dbo<span style="color:#808080">.</span>sp_end_work<span style="color:#0000ff"> </span>@work_id</p>
<p>     <span style="color:#008000">/* Get the next work item */    </span><br />     <span style="color:#0000ff">EXEC</span> [Control]<span style="color:#808080">.</span>dbo<span style="color:#808080">.</span>sp_get_work<span style="color:#0000ff"> </span><span style="color:#ff0000">&#39;BULK&#39;</span><br />         <span style="color:#808080">,</span> @work_id <span style="color:#0000ff">OUTPUT</span><span style="color:#808080">,</span> @assignment <span style="color:#0000ff">OUTPUT</span><span style="color:#808080">,</span> @target <span style="color:#0000ff">OUTPUT</span></p>
<p> <span style="color:#0000ff">END</span></p>
<p> <span style="color:#0000ff">GO</span></div>
</p></div>
</p></div>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<br />
<h4>Keeping track of the SQL scheduler usage</h4>
<p>The&#160; Scheduler_use table should contain a row entry for each CPU available in your system. In our case we will use all 96 available cores so the table contains 96 rows (insert the values 0..95 for scheduler_id). To find out the number of CPU’s quickly&#160; use: </p>
<p>“SELECT cpu_count AS [Logical CPU Count] FROM sys.dm_os_sys_info; “ or check with “master..xp_msver ProcessorCount” .</p>
<p>If you want to “hard” limit the maximum number of parallel bulk insert tasks the table should contains less.</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:88bbee02-8af2-4d53-9b2d-71b5d91786f5" class="wlWriterEditableSmartContent">
<div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt">
<div style="background-color: #ffffff; overflow: auto; padding: 2px 5px;"><span style="color:#0000ff">USE</span> [TPCH_1TB]<br /> <span style="color:#0000ff">GO</span><br /> <span style="color:#008000">&#8211; Object:  Table [dbo].[scheduler_use]   </span><br /> <span style="color:#0000ff">SET</span> <span style="color:#0000ff">ANSI_NULLS</span> <span style="color:#0000ff">ON</span><br /> <span style="color:#0000ff">GO</span></p>
<p> <span style="color:#0000ff">SET</span> <span style="color:#0000ff">QUOTED_IDENTIFIER</span> <span style="color:#0000ff">ON</span><br /> <span style="color:#0000ff">GO</span></p>
<p> <span style="color:#0000ff">CREATE</span> <span style="color:#0000ff">TABLE</span> [dbo]<span style="color:#808080">.</span>[scheduler_use]<span style="color:#808080">(</span><br />     [scheduler_id] [int] <span style="color:#808080">NULL,</span><br />     [session_id] [int] <span style="color:#808080">NULL</span><br /> <span style="color:#808080">)</span> <span style="color:#0000ff">ON</span> [PRIMARY]</p>
<p> <span style="color:#0000ff">GO</span></div>
</p></div>
</p></div>
<h4><a href="http://henkvandervalk.com/wp-content/uploads/2010/08/image28.png" rel="lightbox[617]" title="The Schedule_use table"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="The Schedule_use table" border="0" alt="The Schedule_use table" src="http://henkvandervalk.com/wp-content/uploads/2010/08/image_thumb28.png" width="144" height="175" /></a> </h4>
<h4>&#160;</h4>
<h4>The Control Database</h4>
<p>We created a separate Control Database for the overall housekeeping, like picking jobs from the work queue and keep track of the start flag status in the ready table:</p>
</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:a90e83a2-f8c0-4b1f-a798-497646be1862" class="wlWriterEditableSmartContent">
<div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt">
<div style="background-color: #ffffff; max-height: 300px; overflow: auto; padding: 2px 5px;"><span style="color:#0000ff">USE</span> [Control]<br /> <span style="color:#0000ff">GO</span></p>
<p> <span style="color:#008000">/****** Object:  Table [dbo].[ready]    ******/</span><br /> <span style="color:#0000ff">SET</span> <span style="color:#0000ff">ANSI_NULLS</span> <span style="color:#0000ff">ON</span><br /> <span style="color:#0000ff">GO</span></p>
<p> <span style="color:#0000ff">SET</span> <span style="color:#0000ff">QUOTED_IDENTIFIER</span> <span style="color:#0000ff">ON</span><br /> <span style="color:#0000ff">GO</span></p>
<p> <span style="color:#0000ff">CREATE</span> <span style="color:#0000ff">TABLE</span> [dbo]<span style="color:#808080">.</span>[ready]<span style="color:#808080">(</span><br />     [start] [bit] <span style="color:#808080">NULL</span><br /> <span style="color:#808080">)</span> <span style="color:#0000ff">ON</span> [PRIMARY]</p>
<p> <span style="color:#0000ff">GO</span></div>
</p></div>
</p></div>
</p>
<p>&#160;</p>
<h4>The Work_queue table definition:</h4>
</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:b40a627c-fef0-4626-8ca2-c22a644c4bb7" class="wlWriterEditableSmartContent">
<div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt">
<div style="background-color: #ffffff; max-height: 300px; overflow: auto; padding: 2px 5px;"><span style="color:#0000ff">USE</span> [Control]<br /> <span style="color:#0000ff">GO</span></p>
<p> <span style="color:#008000">/****** Object:  Table [dbo].[work_queue]   ******/</span><br /> <span style="color:#0000ff">SET</span> <span style="color:#0000ff">ANSI_NULLS</span> <span style="color:#0000ff">ON</span><br /> <span style="color:#0000ff">GO</span></p>
<p> <span style="color:#0000ff">SET</span> <span style="color:#0000ff">QUOTED_IDENTIFIER</span> <span style="color:#0000ff">ON</span><br /> <span style="color:#0000ff">GO</span></p>
<p> <span style="color:#0000ff">CREATE</span> <span style="color:#0000ff">TABLE</span> [dbo]<span style="color:#808080">.</span>[work_queue]<span style="color:#808080">(</span><br />     [work_id] [int] <span style="color:#808080">NOT</span> <span style="color:#808080">NULL,</span><br />     [group] [nvarchar]<span style="color:#808080">(</span>128<span style="color:#808080">)</span> <span style="color:#808080">NULL,</span><br />     [priority] [int] <span style="color:#808080">NOT</span> <span style="color:#808080">NULL,</span><br />     [assignment] [nvarchar]<span style="color:#808080">(</span><span style="color:#ff00ff">max</span><span style="color:#808080">)</span> <span style="color:#808080">NULL,</span><br />     [partition] [nvarchar]<span style="color:#808080">(</span><span style="color:#ff00ff">max</span><span style="color:#808080">)</span> <span style="color:#808080">NULL,</span><br />     [target] [nvarchar]<span style="color:#808080">(</span><span style="color:#ff00ff">max</span><span style="color:#808080">)</span> <span style="color:#808080">NULL,</span><br />     [is_active] [bit] <span style="color:#808080">NOT</span> <span style="color:#808080">NULL,</span><br />     [is_done] [bit] <span style="color:#808080">NOT</span> <span style="color:#808080">NULL,</span><br />     [start_date] [datetime] <span style="color:#808080">NULL,</span><br />     [end_date] [datetime] <span style="color:#808080">NULL,</span><br />     [time_ms] [int] <span style="color:#808080">NULL,</span><br />     [logical_reads] [int] <span style="color:#808080">NULL,</span><br />     [reads] [int] <span style="color:#808080">NULL,</span><br />     [writes] [int] <span style="color:#808080">NULL,</span><br />     [cpu_time] [int] <span style="color:#808080">NULL,</span><br />     [scheduler_id] [int] <span style="color:#808080">NULL,</span><br />     [cpu_id] [int] <span style="color:#808080">NULL,</span><br />     [node_id] [int] <span style="color:#808080">NULL,</span><br />     [session_id] [int] <span style="color:#808080">NULL,</span><br />     [user_name] [nvarchar]<span style="color:#808080">(</span>128<span style="color:#808080">)</span> <span style="color:#808080">NULL,</span><br />     [create_date] [datetime] <span style="color:#808080">NOT</span> <span style="color:#808080">NULL</span><br /> <span style="color:#808080">)</span> <span style="color:#0000ff">ON</span> [PRIMARY]</p>
<p> <span style="color:#0000ff">GO</span></div>
</p></div>
</p></div>
</p>
<p>&#160;</p>
<h4>SP sp_get_work</h4>
<p>This stored procedure checks the work-queue for a new work items to process and if a priority is assigned to it. The is_active flag is set when </p>
<p>an item is picked.</p>
<p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:2067d862-12df-4c1a-bbe7-c87d95f0c020" class="wlWriterEditableSmartContent">
<div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt">
<div style="background-color: #ffffff; max-height: 300px; overflow: auto; padding: 2px 5px;"><span style="color:#0000ff">USE</span> [Control]<br /> <span style="color:#0000ff">GO</span></p>
<p> <span style="color:#008000">/****** Object:  StoredProcedure [dbo].[sp_get_work]   ******/</span><br /> <span style="color:#0000ff">SET</span> <span style="color:#0000ff">ANSI_NULLS</span> <span style="color:#0000ff">ON</span><br /> <span style="color:#0000ff">GO</span></p>
<p> <span style="color:#0000ff">SET</span> <span style="color:#0000ff">QUOTED_IDENTIFIER</span> <span style="color:#0000ff">ON</span><br /> <span style="color:#0000ff">GO</span></p>
<p> <span style="color:#0000ff">CREATE</span> <span style="color:#0000ff">PROCEDURE</span> [dbo]<span style="color:#808080">.</span>[sp_get_work] <br />     @group <span style="color:#0000ff">NVARCHAR</span><span style="color:#808080">(</span>128<span style="color:#808080">)</span> <span style="color:#808080">=</span> <span style="color:#808080">NULL</span> <span style="color:#008000">/* The group to get*/</span><br />     <span style="color:#808080">,</span> @work_id <span style="color:#0000ff">INT</span> <span style="color:#808080">=</span> <span style="color:#808080">NULL</span> <span style="color:#0000ff">OUTPUT</span> <span style="color:#008000">/* the work_id assigned */</span><br />     <span style="color:#808080">,</span> @assignment <span style="color:#0000ff">NVARCHAR</span><span style="color:#808080">(</span><span style="color:#ff00ff">MAX</span><span style="color:#808080">)</span> <span style="color:#808080">=</span> <span style="color:#808080">NULL</span> <span style="color:#0000ff">OUTPUT</span> <span style="color:#008000">/* The description of the work to do */</span><br />     <span style="color:#808080">,</span> @target <span style="color:#0000ff">NVARCHAR</span><span style="color:#808080">(</span><span style="color:#ff00ff">MAX</span><span style="color:#808080">)</span> <span style="color:#808080">=</span> <span style="color:#808080">NULL</span> <span style="color:#0000ff">OUTPUT</span> <span style="color:#008000">/* The target to operate on */</span><br />     <span style="color:#808080">,</span> @partition <span style="color:#0000ff">NVARCHAR</span><span style="color:#808080">(</span><span style="color:#ff00ff">MAX</span><span style="color:#808080">)</span> <span style="color:#808080">=</span> <span style="color:#808080">NULL</span> <span style="color:#0000ff">OUTPUT</span> <span style="color:#008000">/* The partition to work on */</span><br /> <span style="color:#0000ff">AS</span> <br /> <span style="color:#008000">/*</span><br /> <span style="color:#008000">    Date: 2008-03-11</span><br /> <span style="color:#008000">    Author: tkejser@microsoft.com</span><br /> <span style="color:#008000">    Purpose: Get a work item from the work_queue in @group</span><br /> <span style="color:#008000">*/</span><br /> <span style="color:#0000ff">SET</span> <span style="color:#0000ff">NOCOUNT</span> <span style="color:#0000ff">ON</span></p>
<p>     <br />     <br /> <span style="color:#008000">/* Gather some data about the connected user */</span><br /> <span style="color:#0000ff">DECLARE</span> @reads <span style="color:#0000ff">INT</span><span style="color:#808080">,</span> @writes <span style="color:#0000ff">INT</span><span style="color:#808080">,</span> @cpu_time <span style="color:#0000ff">INT</span><span style="color:#808080">,</span> @logical_reads <span style="color:#0000ff">INT</span><br /> <span style="color:#0000ff">DECLARE</span> @node_id <span style="color:#0000ff">INT</span><span style="color:#808080">,</span> @scheduler_id <span style="color:#0000ff">INT</span><span style="color:#808080">,</span> @cpu_id <span style="color:#0000ff">INT</span></p>
<p> <span style="color:#0000ff">SELECT</span> @reads <span style="color:#808080">=</span> er<span style="color:#808080">.</span>reads <br />     <span style="color:#808080">,</span> @writes <span style="color:#808080">=</span> er<span style="color:#808080">.</span>writes<br />     <span style="color:#808080">,</span> @logical_reads <span style="color:#808080">=</span> er<span style="color:#808080">.</span>logical_reads<br />     <span style="color:#808080">,</span> @cpu_time <span style="color:#808080">=</span> er<span style="color:#808080">.</span>cpu_time<br />     <span style="color:#808080">,</span> @scheduler_id <span style="color:#808080">=</span> er<span style="color:#808080">.</span>scheduler_id<br />     <span style="color:#808080">,</span> @node_id <span style="color:#808080">=</span> s<span style="color:#808080">.</span>parent_node_id<br />     <span style="color:#808080">,</span> @cpu_id <span style="color:#808080">=</span> s<span style="color:#808080">.</span>cpu_id<br /> <span style="color:#0000ff">FROM</span> <span style="color:#008000">sys</span><span style="color:#808080">.</span><span style="color:#008000">dm_exec_requests</span> er<br /> <span style="color:#808080">INNER</span> <span style="color:#808080">JOIN</span> <span style="color:#008000">sys</span><span style="color:#808080">.</span><span style="color:#008000">dm_os_schedulers</span> s<br />     <span style="color:#0000ff">ON</span> er<span style="color:#808080">.</span>scheduler_id <span style="color:#808080">=</span> s<span style="color:#808080">.</span>scheduler_id<br /> <span style="color:#0000ff">WHERE</span> session_id <span style="color:#808080">=</span> <span style="color:#ff00ff">@@SPID</span></p>
<p> <span style="color:#008000">/* get the work */</span><br /> <span style="color:#0000ff">DECLARE</span> @my_work_id <span style="color:#0000ff">INT</span><br /> <span style="color:#0000ff">DECLARE</span> @my_assignment <span style="color:#0000ff">NVARCHAR</span><span style="color:#808080">(</span><span style="color:#ff00ff">MAX</span><span style="color:#808080">)</span><br />     <span style="color:#808080">,</span> @my_target <span style="color:#0000ff">NVARCHAR</span><span style="color:#808080">(</span><span style="color:#ff00ff">MAX</span><span style="color:#808080">)</span><br />     <span style="color:#808080">,</span> @my_partition <span style="color:#0000ff">NVARCHAR</span><span style="color:#808080">(</span><span style="color:#ff00ff">MAX</span><span style="color:#808080">)</span></p>
<p> <span style="color:#0000ff">UPDATE</span> <span style="color:#0000ff">TOP</span><span style="color:#808080">(</span>1<span style="color:#808080">)</span> work_queue <span style="color:#0000ff">WITH </span><span style="color:#808080">(</span><span style="color:#0000ff">TABLOCKX</span><span style="color:#808080">)</span><br /> <span style="color:#0000ff">SET</span> is_active <span style="color:#808080">=</span> 1<br />     <span style="color:#808080">,</span> [start_date] <span style="color:#808080">=</span> <span style="color:#ff00ff">GETDATE</span><span style="color:#808080">()</span><br />     <span style="color:#808080">,</span> @my_work_id <span style="color:#808080">=</span> work_id<br />     <span style="color:#808080">,</span> @my_assignment <span style="color:#808080">=</span> assignment<br />     <span style="color:#808080">,</span> @my_target <span style="color:#808080">=</span> [target]<br />     <span style="color:#808080">,</span> @my_partition <span style="color:#808080">=</span> [partition]<br />     <span style="color:#808080">,</span> reads <span style="color:#808080">=</span> @reads<br />     <span style="color:#808080">,</span> writes <span style="color:#808080">=</span> @writes<br />     <span style="color:#808080">,</span> cpu_time <span style="color:#808080">=</span> @cpu_time<br />     <span style="color:#808080">,</span> logical_reads <span style="color:#808080">=</span> @logical_reads<br />     <span style="color:#808080">,</span> session_id <span style="color:#808080">=</span> <span style="color:#ff00ff">@@SPID</span><br />     <span style="color:#808080">,</span> [user_name] <span style="color:#808080">=</span> <span style="color:#ff00ff">USER_NAME</span><span style="color:#808080">()</span><br />     <span style="color:#808080">,</span> cpu_id <span style="color:#808080">=</span> @cpu_id<br />     <span style="color:#808080">,</span> scheduler_id <span style="color:#808080">=</span> @scheduler_id<br />     <span style="color:#808080">,</span> node_id <span style="color:#808080">=</span> @node_id<br /> <span style="color:#0000ff">WHERE</span> is_active <span style="color:#808080">=</span> 0<br /> <span style="color:#808080">AND</span> is_done <span style="color:#808080">=</span> 0<br /> <span style="color:#808080">AND</span><span style="color:#0000ff"> </span><span style="color:#808080">(</span>[group] <span style="color:#808080">=</span> @group <span style="color:#808080">OR</span> @group <span style="color:#808080">IS</span> <span style="color:#808080">NULL)</span><br /> <span style="color:#808080">AND</span> priority <span style="color:#808080">=</span><span style="color:#0000ff"> </span><span style="color:#808080">(</span><span style="color:#0000ff">SELECT</span> <span style="color:#ff00ff">MAX</span><span style="color:#808080">(</span>priority<span style="color:#808080">)</span> <span style="color:#008000">/* Get the highest priority item */</span><br />                         <span style="color:#0000ff">FROM</span> work_queue <br />                         <span style="color:#0000ff">WHERE</span> is_active <span style="color:#808080">=</span> 0<br />                             <span style="color:#808080">AND</span> is_done <span style="color:#808080">=</span> 0<br />                             <span style="color:#808080">AND</span><span style="color:#0000ff"> </span><span style="color:#808080">(</span>[group] <span style="color:#808080">=</span> @group <span style="color:#808080">OR</span> @group <span style="color:#808080">IS</span> <span style="color:#808080">NULL))</span></p>
<p> <span style="color:#008000">/* Provide a message if nothing to do */</span><br /> <span style="color:#0000ff">IF</span> @my_work_id <span style="color:#808080">IS</span> <span style="color:#808080">NULL</span> <span style="color:#0000ff">BEGIN</span><br />     <span style="color:#0000ff">PRINT</span> <span style="color:#ff0000">&#39;No work in queue for group = &#39;</span> <span style="color:#808080">+</span> <span style="color:#ff00ff">ISNULL</span><span style="color:#808080">(</span>@group<span style="color:#808080">,</span> <span style="color:#ff0000">&#39;&#39;</span><span style="color:#808080">)</span><br /> <span style="color:#0000ff">END</span></p>
<p> <span style="color:#008000">/* return the values */</span><br /> <span style="color:#0000ff">SELECT</span> @work_id <span style="color:#808080">=</span> @my_work_id<br />     <span style="color:#808080">,    </span>@assignment <span style="color:#808080">=</span> @my_assignment<br />     <span style="color:#808080">,</span> @target <span style="color:#808080">=</span> @my_target<br />     <span style="color:#808080">,</span> @partition <span style="color:#808080">=</span> @my_partition</p>
<p> <span style="color:#0000ff">GO</span></div>
</p></div>
</p></div>
<p>&#160; </p>
<h4>SP end_work</h4>
<p>When the task is finished the “is_done” flag gets set and the session run details are written out to the queue.</p>
</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:1abab42c-f4a7-4e37-8e04-b972d5c3aa1a" class="wlWriterEditableSmartContent">
<div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt">
<div style="background-color: #ffffff; max-height: 300px; overflow: auto; padding: 2px 5px;"><span style="color:#0000ff">USE</span> [Control]<br /> <span style="color:#0000ff">GO</span></p>
<p> <span style="color:#008000">/****** Object:  StoredProcedure [dbo].[sp_end_work] ******/</span><br /> <span style="color:#0000ff">SET</span> <span style="color:#0000ff">ANSI_NULLS</span> <span style="color:#0000ff">ON</span><br /> <span style="color:#0000ff">GO</span></p>
<p> <span style="color:#0000ff">SET</span> <span style="color:#0000ff">QUOTED_IDENTIFIER</span> <span style="color:#0000ff">ON</span><br /> <span style="color:#0000ff">GO</span></p>
<p> <span style="color:#0000ff">CREATE</span> <span style="color:#0000ff">PROCEDURE</span> [dbo]<span style="color:#808080">.</span>[sp_end_work]<br />     @work_id <span style="color:#0000ff">INT</span> <span style="color:#008000">/* The work to mark as ended */</span><br /> <span style="color:#0000ff">AS</span><br /> <span style="color:#008000">/*</span><br /> <span style="color:#008000">    Date: 2009-03-11</span><br /> <span style="color:#008000">    Author: tkejser@microsoft.com</span><br /> <span style="color:#008000">    Purpose: Marks the work in the queue as finished</span><br /> <span style="color:#008000">*/</span><br /> <span style="color:#0000ff">SET</span> <span style="color:#0000ff">NOCOUNT</span> <span style="color:#0000ff">ON</span></p>
<p> <span style="color:#0000ff">DECLARE</span> @reads <span style="color:#0000ff">INT</span><span style="color:#808080">,</span> @writes <span style="color:#0000ff">INT</span><span style="color:#808080">,</span> @cpu_time <span style="color:#0000ff">INT</span><span style="color:#808080">,</span> @logical_reads <span style="color:#0000ff">INT</span></p>
<p> <span style="color:#008000">/* gather some information about the session ending */</span><br /> <span style="color:#0000ff">SELECT</span> @reads <span style="color:#808080">=</span> er<span style="color:#808080">.</span>reads <br />     <span style="color:#808080">,</span> @writes <span style="color:#808080">=</span> er<span style="color:#808080">.</span>writes<br />     <span style="color:#808080">,</span> @logical_reads <span style="color:#808080">=</span> er<span style="color:#808080">.</span>logical_reads<br />     <span style="color:#808080">,</span> @cpu_time <span style="color:#808080">=</span> er<span style="color:#808080">.</span>cpu_time<br /> <span style="color:#0000ff">FROM</span> <span style="color:#008000">sys</span><span style="color:#808080">.</span><span style="color:#008000">dm_exec_requests</span> er<br /> <span style="color:#0000ff">WHERE</span> session_id <span style="color:#808080">=</span> <span style="color:#ff00ff">@@SPID</span></p>
<p> <span style="color:#0000ff">UPDATE</span> work_queue <br /> <span style="color:#0000ff">SET</span> is_done <span style="color:#808080">=</span> 1<br />     <span style="color:#808080">,</span> is_active <span style="color:#808080">=</span> 0<br />     <span style="color:#808080">,</span> end_date <span style="color:#808080">=</span> <span style="color:#ff00ff">GETDATE</span><span style="color:#808080">()</span><br />     <span style="color:#808080">,</span> time_ms <span style="color:#808080">=</span> <span style="color:#ff00ff">DATEDIFF</span><span style="color:#808080">(</span>ms<span style="color:#808080">,</span> [start_date]<span style="color:#808080">,</span> <span style="color:#ff00ff">GETDATE</span><span style="color:#808080">())    </span><br />     <span style="color:#808080">,</span> cpu_time <span style="color:#808080">=</span> @cpu_time <span style="color:#808080">-</span> cpu_time <br />     <span style="color:#808080">,</span> logical_reads <span style="color:#808080">=</span> @logical_reads <span style="color:#808080">-</span> logical_reads<br />     <span style="color:#808080">,</span> reads <span style="color:#808080">=</span> @reads <span style="color:#808080">-</span> reads<br />     <span style="color:#808080">,</span> writes <span style="color:#808080">=</span> @writes <span style="color:#808080">-</span> writes<br /> <span style="color:#0000ff">WHERE</span> work_id <span style="color:#808080">=</span> @work_id</p>
<p> <span style="color:#0000ff">GO</span></div>
</p></div>
</p></div>
<p>That’s all there is to it!&#160; Or… maybe there’s something else to take into account when writing out data at high speed to SSD storage. What about the SSD “wearing effect” or housekeeping operations that are going on in the background&#160; to spread the write load evenly across all the chips ?</p>
<h3>The DSI Effect </h3>
<p>Until a couple of weeks ago when I was investigating performance logs from a customer who was using these entry level PCI-E SSD cards, I never realized that the DSI Solid state units which I have been stress testing very hard for months (actually, since January 2009 already) do not show any noticeable form of write throughput degradation or even latency increase under high pressure, not even when hammering them for hours. and I wrote Petabytes of data to them by now. Reason: the backend write capacity outperforms the maximum load that the front-end ports can ever provide. Lucky me!&#160; (However when your budget is a bit tight and only allows you to buy some PCI-E SSD cards, make sure you check the Virtual File Stats (sys.dm_io_virtual_file_stats) to see how much data has been written to tempdb or any of the database files that you would like to store on SSD, and predict the write IO workload on an hourly or daily basis). </p>
<p><a href="http://henkvandervalk.com/wp-content/uploads/2010/08/image29.png" rel="lightbox[617]" title="a 2TB DSI 3600 uncovered; on the left the 8 Fiber ports and on the right the SLC SSD chips"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="a 2TB DSI 3600 uncovered; on the left the 8 Fiber ports and on the right the SLC SSD chips" border="0" alt="a 2TB DSI 3600 uncovered; on the left the 8 Fiber ports and on the right the SLC SSD chips" src="http://henkvandervalk.com/wp-content/uploads/2010/08/image_thumb29.png" width="414" height="289" /></a> </p>
<h3>Additional Readings</h3>
<p>To read in more detail about the products we use or all ins-and-outs on bulk inserting data, here are some links: </p>
<ul>
<li>The Unisys ES7000 Server, <a href="http://www.app3.unisys.com/7600R/index.html" target="_blank">Model 7600R</a>,       <br />with 16 x Intel 6-core X7460 CPU’s (= 96 cores) and 512 GB RAM (Up to 1 TB) </li>
<li>Dynamic Solutions&#160; SSD Storage Solutions: <a title="http://www.dynamicsolutions.com/dsi3600" href="http://www.dynamicsolutions.com/dsi3600">http://www.dynamicsolutions.com/dsi3600</a> </li>
<li>SQL Powerrack:&#160; <a href="http://www.sqlpowerrack.com">www.sqlpowerrack.com</a> </li>
<li>The Data Loading Performance Guide:      <br /><a href="http://msdn.microsoft.com/en-us/library/dd425070.aspx">http://msdn.microsoft.com/en-us/library/dd425070.aspx</a> </li>
<li>The 2008 ETL World record: <a href="http://msdn.microsoft.com/en-us/library/dd537533.aspx">http://msdn.microsoft.com/en-us/library/dd537533.aspx</a> </li>
</ul>
<p>&#160;</p>
<h3>Wrap-up</h3>
<p>From the very early builds of SQL Server 2008 R2 with 64+ core support enabled it has been very much fun to drive 96 cores Unisys ES7000 servers to their limits;finally a Windows app that can benefit from so many cores! But even more important, SQL 2008 R2 has always been running smoothly and never failed. It’s also great to see how SQL Server benefits from the sustained low latency disk IO’s for both reading and writing at the very high speeds that the DSI SSD units provide. When you are in need of a high performance system that has to move Terabytes of data around on an hourly- or daily basis, consider the Unisys <a href="http://www.sqlpowerrack.com/" target="_blank">SQL Powerrack</a> offering. Or just remember these numbers: loading 1 Terabyte of data from flat files into SQL Server 2008 R2 within 10 minutes, that’s like reading more than 2 Gigabyte a second and writing almost 1750 Megabyte/sec !;-)</p>
<p> <!--aiospwlwbstart<br />
aiosp_title=Bulk Inserting 1 TeraByte of data within 10 minutes with SQL Server 2008 R2 Datacenter Edition<br />
aiosp_keywords=Unisys, DSI, SQL 2008 R2, SSD, tuning tips<br />
aiosp_description=High-Speed Data loading with SQL 2008 R2 on a 96 core Unisys ES7000 Server with DSI Solid State Storage.<br />
aiospwlwbsend--></p>
<img src="http://feeds.feedburner.com/~r/HenksTechBlog/~4/En6ixxWfa10" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://henkvandervalk.com/sql2008-r2-dce-on-a-96-core-unisys-es7000-server-with-dsi-solid-state-storage-bulk-inserting-1-terabyte-within-10-minutes/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://henkvandervalk.com/sql2008-r2-dce-on-a-96-core-unisys-es7000-server-with-dsi-solid-state-storage-bulk-inserting-1-terabyte-within-10-minutes</feedburner:origLink></item>
	</channel>
</rss><!-- Dynamic page generated in 3.559 seconds. --><!-- Cached page generated by WP-Super-Cache on 2013-05-24 02:20:46 -->
