<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://sqlblog.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Adam Machanic</title><link>http://sqlblog.com/blogs/adam_machanic/default.aspx</link><description>Adam Machanic, Boston-based independent database consultant, writer, and speaker, shares his experiences with programming, performance tuning, and optimizing SQL Server 2000, 2005, and 2008, in conjunction with related technologies such as .NET.</description><dc:language>en</dc:language><generator>CommunityServer 2.1 SP2 (Build: 61129.1)</generator><item><title>The Hidden Costs of INSERT EXEC</title><link>http://sqlblog.com/blogs/adam_machanic/archive/2009/06/25/the-hidden-costs-of-insert-exec.aspx</link><pubDate>Thu, 25 Jun 2009 20:19:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:14921</guid><dc:creator>Adam Machanic</dc:creator><slash:comments>9</slash:comments><comments>http://sqlblog.com/blogs/adam_machanic/comments/14921.aspx</comments><wfw:commentRss>http://sqlblog.com/blogs/adam_machanic/commentrss.aspx?PostID=14921</wfw:commentRss><description>INSERT and EXEC: relational brothers in arms, helping you get your data and then put it somewhere. But like all brothers, their relationship has its ups and downs and sometimes you need to look just below the surface to see the real issues. In this post...(&lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2009/06/25/the-hidden-costs-of-insert-exec.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://sqlblog.com/aggbug.aspx?PostID=14921" width="1" height="1"&gt;</description><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/Performance/default.aspx">Performance</category><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/DMVs/default.aspx">DMVs</category><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/insert/default.aspx">insert</category><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/exec/default.aspx">exec</category></item><item><title>SQL PFE Team: New Must-Read Blog? </title><link>http://sqlblog.com/blogs/adam_machanic/archive/2009/06/18/sql-pfe-team-new-must-read-blog.aspx</link><pubDate>Thu, 18 Jun 2009 20:01:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:14751</guid><dc:creator>Adam Machanic</dc:creator><slash:comments>2</slash:comments><comments>http://sqlblog.com/blogs/adam_machanic/comments/14751.aspx</comments><wfw:commentRss>http://sqlblog.com/blogs/adam_machanic/commentrss.aspx?PostID=14751</wfw:commentRss><description>Several months ago I asked Joe Sack why his team, the SQL Server Premier Field Engineers, wasn't blogging and sharing the insights that result from their work with a number of high-end SQL Server customers. He replied that he thought it was a great idea,...(&lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2009/06/18/sql-pfe-team-new-must-read-blog.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://sqlblog.com/aggbug.aspx?PostID=14751" width="1" height="1"&gt;</description><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/blogs/default.aspx">blogs</category></item><item><title>Demos From Cape Cod .NET: T-SQL Power! Presentation</title><link>http://sqlblog.com/blogs/adam_machanic/archive/2009/06/18/demos-from-cape-cod-net-t-sql-power-presentation.aspx</link><pubDate>Thu, 18 Jun 2009 16:05:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:14749</guid><dc:creator>Adam Machanic</dc:creator><slash:comments>0</slash:comments><comments>http://sqlblog.com/blogs/adam_machanic/comments/14749.aspx</comments><wfw:commentRss>http://sqlblog.com/blogs/adam_machanic/commentrss.aspx?PostID=14749</wfw:commentRss><description>On Tuesday night I was honored to present a new talk to the Cape Cod .NET Users Group that meets in Plymouth, MA. The talk is called "T-SQL Power! Learning to Harness the Under-Used OVER Clause". Following is the abstract for the talk: First introduced...(&lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2009/06/18/demos-from-cape-cod-net-t-sql-power-presentation.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://sqlblog.com/aggbug.aspx?PostID=14749" width="1" height="1"&gt;</description><enclosure url="http://sqlblog.com/blogs/adam_machanic/attachment/14749.ashx" length="4365" type="application/zip" /><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/Scripts/default.aspx">Scripts</category><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/demos/default.aspx">demos</category><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/row_5F00_number/default.aspx">row_number</category><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/OVER+clause/default.aspx">OVER clause</category></item><item><title>Grouped String Concatenation: ... The Winner Is ...</title><link>http://sqlblog.com/blogs/adam_machanic/archive/2009/05/31/grouped-string-concatenation-the-winner-is.aspx</link><pubDate>Sun, 31 May 2009 20:07:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:14360</guid><dc:creator>Adam Machanic</dc:creator><slash:comments>16</slash:comments><comments>http://sqlblog.com/blogs/adam_machanic/comments/14360.aspx</comments><wfw:commentRss>http://sqlblog.com/blogs/adam_machanic/commentrss.aspx?PostID=14360</wfw:commentRss><description>&lt;p&gt;After weeks of putting it off, I finally found the time and spent the last day and a half judging the &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2009/02/27/t-sql-challenge-grouped-string-concatenation.aspx"&gt;Grouped String Concatenation Challenge&lt;/a&gt;. I would like to congratulate the winner, &lt;a href="http://weblogs.sqlteam.com/peterl/"&gt;&lt;b&gt;Peter Larsson&lt;/b&gt;&lt;/a&gt;, who submitted a great query and walks away with a shiny new MSDN Premium subscription.&lt;/p&gt;&lt;p&gt;For those who are interested, following is a breakdown of the judging process, along with some commentary: &lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;u&gt;&lt;b&gt;Submission Process&lt;/b&gt;&lt;/u&gt; &lt;br&gt;&lt;/p&gt;&lt;p&gt;To begin with, e-mails. As I mentioned in the first post, I ignored all e-mails that didn't follow the directions. Luckily this was only a few submissions. I felt it rather odd that people would spend a not insignificant amount of time working up a solution only to not bother to read the guidelines thoroughly. But that's human nature, I suppose.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;u&gt;&lt;b&gt;Round 1&lt;/b&gt;&lt;/u&gt; &lt;br&gt;&lt;/p&gt;&lt;p&gt;Once I collected all of the queries that followed the e-mail rules (all of which are included in the attached ZIP file), I began testing against an expanded version of AdventureWorks (the script for that is also included). I decided to &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2009/03/15/the-grouped-string-concatenation-challenge-is-closed.aspx"&gt;eliminate any queries that did not produce the correct output data&lt;/a&gt; based on my sample set, or which took longer than 30 seconds to complete. The majority of queries did complete in a reasonable amount of time, and many were eliminated because the output simply wasn't correct. The biggest issue was ordering of the elements in the comma-delimited sets. I also deducted points from one person's entry because of invalid column names, but I decided to let the entry ride to the next round.&lt;/p&gt;&lt;p&gt;An important side note is that I created this competition with the sole intention of discovering new and different ways to do grouped string concatenation, and my hope was that someone would come up with a clever, fast solution. Unfortunately, that didn't happen, and every submission that used any technique except FOR XML PATH was eliminated in the first round of testing. I received some extremely creative solutions from a couple of people and I would like to mention them here:&lt;br&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Alejandro Mesa's submissions made use of various XQuery techniques, and are very interesting to look at, although fairly slow&lt;/li&gt;&lt;li&gt;Dean Cochrane's submission used an interesting idea of doing a MAX(CASE ...) pivot for the lists. Alas, the product names lists were not correct, so the submission didn't make it to the stress testing phase&lt;/li&gt;&lt;li&gt;Scott Coleman tried a similar technique, actually using the PIVOT keyword. Unfortunately, this ran for over 200 seconds, so it was eliminated&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Also interesting to note is that a few people tried recursive CTE solutions. These were all cancelled at the 300 second mark. Recursive CTEs, &lt;a href="http://sqlblog.com/blogs/linchi_shea/archive/2009/04/16/recursive-sql-queries-how-do-they-work.aspx"&gt;as mentioned before on here on SQLblog&lt;/a&gt;, simply do not scale in their current implementation.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;u&gt;&lt;b&gt;Round 2&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;&lt;p&gt;After tabulating the Round 1 results I was left with 18 queries, and some obvious contenders.&amp;nbsp; I ran each query through a SQLQueryStress session with 10 threads running 5 iterations each. In this phase the queries were separated into fairly distinct groups: Those that ran for around 5 minutes, those that ran for around 7-8 minutes, and those that ran longer. These groups were based, not surprisingly, on how much attention was paid by the query writers to the little details. For example, Peter Larsson's winning query cut down on logical reads dramatically by doing some of the grouping in a derived table, rather than in the outermost query as some of the other submissions did. &lt;/p&gt;&lt;p&gt;Lesson learned: When doing aggregations, especially when joining a lot of tables, think about what you're &lt;i&gt;really&lt;/i&gt; aggregating, and do the aggregation as early as possible. For example, if you need to aggregate sales per customer and get customer names, do the aggregation of the sales numbers first, &lt;i&gt;then&lt;/i&gt; join out to get the customer names. Otherwise the query processor is forced to do more work than it has to do, and your query won't be as fast. Peter and a few other contestants understood this distinction and wrote queries that were much faster as a result.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;u&gt;&lt;b&gt;Round 3&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;&lt;p&gt;Round 2 eliminated 4 queries, leaving me with 14 to judge based on query style. In order to judge consistently, I came up with 10 factors. A query was allotted 500 points to start, and failure to meet each factor resulted in a 50 point penalty. These factors were:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Consistent Indentation&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Does the query use the same rules for indentation in all parts? This is huge for readability and helps people understand where each section of the query starts and ends.&lt;br&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Consistent Capitalization&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Does the query use the same rules for capitalization throughout? For example, keywords should be either all capitalized, or all lowercase.&lt;br&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Capitalize Keywords&lt;/li&gt;&lt;ul&gt;&lt;li&gt;I like to see keywords capitalized.&lt;br&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Use AS for Alias Names&lt;/li&gt;&lt;ul&gt;&lt;li&gt;AS is optional, and I've left it out in many queries I've written. But the more of other peoples' code I read, the more I realize that it really does help on the readability front. Use it. Always.&lt;br&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Follow Capitalization of Base Tables/Columns&lt;/li&gt;&lt;ul&gt;&lt;li&gt;If the base table is called OrderHeader, I want to see it used as OrderHeader when referenced in your query, rather than orderheader. A trainer I know found this out the hard way, when he reinstalled SQL Server on his laptop shortly before a training session, and used a case-sensitive collation rather than his previously-installed case-insensitive collation. He had been careless in adhering to capitalization for his training materials, and discovered the issue in front of the class. Oops.&lt;br&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Long Horizontal Lists&lt;/li&gt;&lt;ul&gt;&lt;li&gt;I don't like horizontal scrolling, and I find long lists difficult to read.&lt;br&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Consistent Vertical Lists&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Put either a comma after each element or before each element, not both. Indent your lists the same way throughout. If you indent some items below the SELECT, don't put other items on the same line as the SELECT (or GROUP BY, or ORDER BY, etc)&lt;br&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Alignment of Delimiters&lt;/li&gt;&lt;ul&gt;&lt;li&gt;I follow a .NET-inspired style where I put delimiters on their own lines, and line them up vertically. This gives my code what I feel is an airy, easy-to-read feel. When reading others' code I look for some kind of alignment. Failure to align delimiters makes it very difficult to understand, again, where one section begins and another ends. By the way, common delimiters for this challenge included both parens and CASE...END.&lt;br&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Comments&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Does the query have comments? Are the comments useful in understanding the logic?&lt;br&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Aesthetics&lt;/li&gt;&lt;ul&gt;&lt;li&gt;This is perhaps the most subjective. My general feeling on how I enjoyed reading the code. &lt;br&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;p&gt;All in all, the queries were pretty good. I would like to call out Rick Halliday, who had the highest score in this round with some very well formatted and highly readable code.&lt;br&gt;&lt;br&gt;&lt;u&gt;&lt;b&gt;&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;&lt;p&gt;&lt;u&gt;&lt;b&gt;Round 4&lt;/b&gt;&lt;/u&gt;&lt;br&gt;&lt;br&gt;After judging Round 3 I tallied all of the scores and was left with a tie for top 3:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Rick Halliday&lt;/li&gt;&lt;li&gt;Leonid Koyfman&lt;/li&gt;&lt;li&gt;Peter Larsson's query #4&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;All three of these queries were well thought out, but only one could win, so I took another pass through each. Rick's query, though extremely well written and readable, was eliminetad first due to the fact that it performed worse than the other two. This left Leonid and Peter. It was a tough choice, but I had to give the prize to Peter for taking the time to really think through the problem and figure out exactly how best to do the aggregations. Leonid was a very, &lt;i&gt;very &lt;/i&gt;close second, and I really wish I had a consolation prize for him.&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;u&gt;&lt;b&gt;The End&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;&lt;p&gt;And that's that. Thank you to everyone who participated in the challenge. I hope it was as much a learning experience for you as it was for me. Congratulations again to Peter. All of the materials are attached in the ZIP file; please let me know if you have any questions, comments, etc. &lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;BR&gt;&lt;div class = "shareblock"&gt;&lt;span class = "shareblockTitle"&gt;Share this post:&lt;/span&gt;&lt;span class = "shareblockLink"&gt; &lt;a href = "mailto:?subject=Grouped String Concatenation: ... The Winner Is ...&amp;amp;body=Seen on SQLblog.com: %0A%0A%09Grouped String Concatenation: ... The Winner Is ...%0A%0Ahttp://sqlblog.com/blogs/adam_machanic/archive/2009/05/31/grouped-string-concatenation-the-winner-is.aspx" target="_blank" title = "Email Grouped String Concatenation: ... The Winner Is ..."&gt;email it!&lt;/a&gt; |  &lt;a href = "http://del.icio.us/post?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/05/31/grouped-string-concatenation-the-winner-is.aspx&amp;amp;title=Grouped+String+Concatenation%3a+...+The+Winner+Is+..." target="_blank" title = "Submit Grouped String Concatenation: ... The Winner Is ... to del.icio.us"&gt;bookmark it!&lt;/a&gt; |  &lt;a href = "http://www.digg.com/submit?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/05/31/grouped-string-concatenation-the-winner-is.aspx&amp;amp;phase=2" target="_blank" title = "Submit Grouped String Concatenation: ... The Winner Is ... to digg.com"&gt;digg it!&lt;/a&gt; |  &lt;a href = "http://reddit.com/submit?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/05/31/grouped-string-concatenation-the-winner-is.aspx&amp;amp;title=Grouped+String+Concatenation%3a+...+The+Winner+Is+..." target="_blank" title = "Submit Grouped String Concatenation: ... The Winner Is ... to reddit.com"&gt;reddit!&lt;/a&gt; |  &lt;a href = "http://www.dotnetkicks.com/submit/?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/05/31/grouped-string-concatenation-the-winner-is.aspx&amp;amp;title=Grouped+String+Concatenation%3a+...+The+Winner+Is+..." target="_blank" title = "Submit Grouped String Concatenation: ... The Winner Is ... to DotNetKicks"&gt;kick it!&lt;/a&gt; |  &lt;a href = "https://favorites.live.com/quickadd.aspx?marklet=1&amp;amp;mkt=en-us&amp;amp;url=http://sqlblog.com/blogs/adam_machanic/archive/2009/05/31/grouped-string-concatenation-the-winner-is.aspx&amp;amp;title=Grouped+String+Concatenation%3a+...+The+Winner+Is+...&amp;amp;;top=1" target="_blank" title = "Add Grouped String Concatenation: ... The Winner Is ... to Live Bookmarks"&gt;live it!&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;img src="http://info.sqlblog.com/a.aspx?ZoneID=0&amp;BannerID=12&amp;AdvertiserID=1&amp;CampaignID=12&amp;Task=Get&amp;Mode=TEXT&amp;SiteID=1&amp;RandomNumber=463323" width="1" height="1" border="0"&gt;&lt;img src="http://sqlblog.com/aggbug.aspx?PostID=14360" width="1" height="1"&gt;</description><enclosure url="http://sqlblog.com/blogs/adam_machanic/attachment/14360.ashx" length="52865" type="application/x-zip-compressed" /><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/T-SQL/default.aspx">T-SQL</category><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/challenge/default.aspx">challenge</category><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/concatenation/default.aspx">concatenation</category></item><item><title>Peter DeBetta and I Rock .NET</title><link>http://sqlblog.com/blogs/adam_machanic/archive/2009/05/19/peter-debetta-and-i-rock-net.aspx</link><pubDate>Tue, 19 May 2009 14:10:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:14152</guid><dc:creator>Adam Machanic</dc:creator><slash:comments>0</slash:comments><comments>http://sqlblog.com/blogs/adam_machanic/comments/14152.aspx</comments><wfw:commentRss>http://sqlblog.com/blogs/adam_machanic/commentrss.aspx?PostID=14152</wfw:commentRss><description>&lt;p&gt;... or something like that. &lt;/p&gt;&lt;p&gt;We're &lt;a href="http://www.dotnetrocks.com/default.aspx?showNum=447"&gt;featured on this week's .NET Rocks! show&lt;/a&gt;, discussing some of the intricacies of database design with Richard and Carl. Enjoy!&lt;br&gt;&lt;/p&gt;
&lt;BR&gt;&lt;div class = "shareblock"&gt;&lt;span class = "shareblockTitle"&gt;Share this post:&lt;/span&gt;&lt;span class = "shareblockLink"&gt; &lt;a href = "mailto:?subject=Peter DeBetta and I Rock .NET&amp;amp;body=Seen on SQLblog.com: %0A%0A%09Peter DeBetta and I Rock .NET%0A%0Ahttp://sqlblog.com/blogs/adam_machanic/archive/2009/05/19/peter-debetta-and-i-rock-net.aspx" target="_blank" title = "Email Peter DeBetta and I Rock .NET"&gt;email it!&lt;/a&gt; |  &lt;a href = "http://del.icio.us/post?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/05/19/peter-debetta-and-i-rock-net.aspx&amp;amp;title=Peter+DeBetta+and+I+Rock+.NET" target="_blank" title = "Submit Peter DeBetta and I Rock .NET to del.icio.us"&gt;bookmark it!&lt;/a&gt; |  &lt;a href = "http://www.digg.com/submit?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/05/19/peter-debetta-and-i-rock-net.aspx&amp;amp;phase=2" target="_blank" title = "Submit Peter DeBetta and I Rock .NET to digg.com"&gt;digg it!&lt;/a&gt; |  &lt;a href = "http://reddit.com/submit?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/05/19/peter-debetta-and-i-rock-net.aspx&amp;amp;title=Peter+DeBetta+and+I+Rock+.NET" target="_blank" title = "Submit Peter DeBetta and I Rock .NET to reddit.com"&gt;reddit!&lt;/a&gt; |  &lt;a href = "http://www.dotnetkicks.com/submit/?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/05/19/peter-debetta-and-i-rock-net.aspx&amp;amp;title=Peter+DeBetta+and+I+Rock+.NET" target="_blank" title = "Submit Peter DeBetta and I Rock .NET to DotNetKicks"&gt;kick it!&lt;/a&gt; |  &lt;a href = "https://favorites.live.com/quickadd.aspx?marklet=1&amp;amp;mkt=en-us&amp;amp;url=http://sqlblog.com/blogs/adam_machanic/archive/2009/05/19/peter-debetta-and-i-rock-net.aspx&amp;amp;title=Peter+DeBetta+and+I+Rock+.NET&amp;amp;;top=1" target="_blank" title = "Add Peter DeBetta and I Rock .NET to Live Bookmarks"&gt;live it!&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;img src="http://info.sqlblog.com/a.aspx?ZoneID=0&amp;BannerID=12&amp;AdvertiserID=1&amp;CampaignID=12&amp;Task=Get&amp;Mode=TEXT&amp;SiteID=1&amp;RandomNumber=463323" width="1" height="1" border="0"&gt;&lt;img src="http://sqlblog.com/aggbug.aspx?PostID=14152" width="1" height="1"&gt;</description><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/.NET+Rocks/default.aspx">.NET Rocks</category></item><item><title>Demos - TechEd DAT402 - Microsoft SQL Server 2008: Performance Profiling and Troubleshooting with Extended Events</title><link>http://sqlblog.com/blogs/adam_machanic/archive/2009/05/14/demos-teched-dat402-microsoft-sql-server-2008-performance-profiling-and-troubleshooting-with-extended-events.aspx</link><pubDate>Thu, 14 May 2009 18:52:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:14057</guid><dc:creator>Adam Machanic</dc:creator><slash:comments>3</slash:comments><comments>http://sqlblog.com/blogs/adam_machanic/comments/14057.aspx</comments><wfw:commentRss>http://sqlblog.com/blogs/adam_machanic/commentrss.aspx?PostID=14057</wfw:commentRss><description>&lt;p&gt;Whew! Another TechEd session completed, and now I'm done for the week. Thanks to everyone who joined me today; I had a fantastic time talking about the ins and outs of Extended Events.&amp;nbsp; Demos are attached.&amp;nbsp; I realize how complex some of these topics are, so please feel free to drop me a note in the comments here with any questions or concerns.&amp;nbsp; Also stay tuned--I'm continuing to work with and improve these samples and will be publishing updates from time to time in the coming months.&lt;br&gt;&lt;/p&gt;
&lt;BR&gt;&lt;div class = "shareblock"&gt;&lt;span class = "shareblockTitle"&gt;Share this post:&lt;/span&gt;&lt;span class = "shareblockLink"&gt; &lt;a href = "mailto:?subject=Demos - TechEd DAT402 - Microsoft SQL Server 2008: Performance Profiling and Troubleshooting with Extended Events&amp;amp;body=Seen on SQLblog.com: %0A%0A%09Demos - TechEd DAT402 - Microsoft SQL Server 2008: Performance Profiling and Troubleshooting with Extended Events%0A%0Ahttp://sqlblog.com/blogs/adam_machanic/archive/2009/05/14/demos-teched-dat402-microsoft-sql-server-2008-performance-profiling-and-troubleshooting-with-extended-events.aspx" target="_blank" title = "Email Demos - TechEd DAT402 - Microsoft SQL Server 2008: Performance Profiling and Troubleshooting with Extended Events"&gt;email it!&lt;/a&gt; |  &lt;a href = "http://del.icio.us/post?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/05/14/demos-teched-dat402-microsoft-sql-server-2008-performance-profiling-and-troubleshooting-with-extended-events.aspx&amp;amp;title=Demos+-+TechEd+DAT402+-+Microsoft+SQL+Server+2008%3a+Performance+Profiling+and+Troubleshooting+with+Extended+Events" target="_blank" title = "Submit Demos - TechEd DAT402 - Microsoft SQL Server 2008: Performance Profiling and Troubleshooting with Extended Events to del.icio.us"&gt;bookmark it!&lt;/a&gt; |  &lt;a href = "http://www.digg.com/submit?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/05/14/demos-teched-dat402-microsoft-sql-server-2008-performance-profiling-and-troubleshooting-with-extended-events.aspx&amp;amp;phase=2" target="_blank" title = "Submit Demos - TechEd DAT402 - Microsoft SQL Server 2008: Performance Profiling and Troubleshooting with Extended Events to digg.com"&gt;digg it!&lt;/a&gt; |  &lt;a href = "http://reddit.com/submit?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/05/14/demos-teched-dat402-microsoft-sql-server-2008-performance-profiling-and-troubleshooting-with-extended-events.aspx&amp;amp;title=Demos+-+TechEd+DAT402+-+Microsoft+SQL+Server+2008%3a+Performance+Profiling+and+Troubleshooting+with+Extended+Events" target="_blank" title = "Submit Demos - TechEd DAT402 - Microsoft SQL Server 2008: Performance Profiling and Troubleshooting with Extended Events to reddit.com"&gt;reddit!&lt;/a&gt; |  &lt;a href = "http://www.dotnetkicks.com/submit/?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/05/14/demos-teched-dat402-microsoft-sql-server-2008-performance-profiling-and-troubleshooting-with-extended-events.aspx&amp;amp;title=Demos+-+TechEd+DAT402+-+Microsoft+SQL+Server+2008%3a+Performance+Profiling+and+Troubleshooting+with+Extended+Events" target="_blank" title = "Submit Demos - TechEd DAT402 - Microsoft SQL Server 2008: Performance Profiling and Troubleshooting with Extended Events to DotNetKicks"&gt;kick it!&lt;/a&gt; |  &lt;a href = "https://favorites.live.com/quickadd.aspx?marklet=1&amp;amp;mkt=en-us&amp;amp;url=http://sqlblog.com/blogs/adam_machanic/archive/2009/05/14/demos-teched-dat402-microsoft-sql-server-2008-performance-profiling-and-troubleshooting-with-extended-events.aspx&amp;amp;title=Demos+-+TechEd+DAT402+-+Microsoft+SQL+Server+2008%3a+Performance+Profiling+and+Troubleshooting+with+Extended+Events&amp;amp;;top=1" target="_blank" title = "Add Demos - TechEd DAT402 - Microsoft SQL Server 2008: Performance Profiling and Troubleshooting with Extended Events to Live Bookmarks"&gt;live it!&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;img src="http://info.sqlblog.com/a.aspx?ZoneID=0&amp;BannerID=12&amp;AdvertiserID=1&amp;CampaignID=12&amp;Task=Get&amp;Mode=TEXT&amp;SiteID=1&amp;RandomNumber=463323" width="1" height="1" border="0"&gt;&lt;img src="http://sqlblog.com/aggbug.aspx?PostID=14057" width="1" height="1"&gt;</description><enclosure url="http://sqlblog.com/blogs/adam_machanic/attachment/14057.ashx" length="7715" type="application/x-zip-compressed" /><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/TechEd/default.aspx">TechEd</category><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/extended+events/default.aspx">extended events</category></item><item><title>Demos - TechEd DAT305 - Best Practices for Exception Handling and Defensive Programming in Microsoft SQL Server</title><link>http://sqlblog.com/blogs/adam_machanic/archive/2009/05/13/demos-teched-dat305-best-practices-for-exception-handling-and-defensive-programming-in-microsoft-sql-server.aspx</link><pubDate>Wed, 13 May 2009 23:46:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:14030</guid><dc:creator>Adam Machanic</dc:creator><slash:comments>5</slash:comments><comments>http://sqlblog.com/blogs/adam_machanic/comments/14030.aspx</comments><wfw:commentRss>http://sqlblog.com/blogs/adam_machanic/commentrss.aspx?PostID=14030</wfw:commentRss><description>&lt;p&gt;A huge thank you to everyone who attended today's session on exception handling! I had a great time and got some very good, on-point questions from the audience.&amp;nbsp; As promised, the demos are attached to this blog post.&amp;nbsp; Please let me know in the comments if you have any questions (whether or not you attended--everyone is allowed to join the party). &lt;br&gt;&lt;/p&gt;
&lt;BR&gt;&lt;div class = "shareblock"&gt;&lt;span class = "shareblockTitle"&gt;Share this post:&lt;/span&gt;&lt;span class = "shareblockLink"&gt; &lt;a href = "mailto:?subject=Demos - TechEd DAT305 - Best Practices for Exception Handling and Defensive Programming in Microsoft SQL Server&amp;amp;body=Seen on SQLblog.com: %0A%0A%09Demos - TechEd DAT305 - Best Practices for Exception Handling and Defensive Programming in Microsoft SQL Server%0A%0Ahttp://sqlblog.com/blogs/adam_machanic/archive/2009/05/13/demos-teched-dat305-best-practices-for-exception-handling-and-defensive-programming-in-microsoft-sql-server.aspx" target="_blank" title = "Email Demos - TechEd DAT305 - Best Practices for Exception Handling and Defensive Programming in Microsoft SQL Server"&gt;email it!&lt;/a&gt; |  &lt;a href = "http://del.icio.us/post?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/05/13/demos-teched-dat305-best-practices-for-exception-handling-and-defensive-programming-in-microsoft-sql-server.aspx&amp;amp;title=Demos+-+TechEd+DAT305+-+Best+Practices+for+Exception+Handling+and+Defensive+Programming+in+Microsoft+SQL+Server" target="_blank" title = "Submit Demos - TechEd DAT305 - Best Practices for Exception Handling and Defensive Programming in Microsoft SQL Server to del.icio.us"&gt;bookmark it!&lt;/a&gt; |  &lt;a href = "http://www.digg.com/submit?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/05/13/demos-teched-dat305-best-practices-for-exception-handling-and-defensive-programming-in-microsoft-sql-server.aspx&amp;amp;phase=2" target="_blank" title = "Submit Demos - TechEd DAT305 - Best Practices for Exception Handling and Defensive Programming in Microsoft SQL Server to digg.com"&gt;digg it!&lt;/a&gt; |  &lt;a href = "http://reddit.com/submit?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/05/13/demos-teched-dat305-best-practices-for-exception-handling-and-defensive-programming-in-microsoft-sql-server.aspx&amp;amp;title=Demos+-+TechEd+DAT305+-+Best+Practices+for+Exception+Handling+and+Defensive+Programming+in+Microsoft+SQL+Server" target="_blank" title = "Submit Demos - TechEd DAT305 - Best Practices for Exception Handling and Defensive Programming in Microsoft SQL Server to reddit.com"&gt;reddit!&lt;/a&gt; |  &lt;a href = "http://www.dotnetkicks.com/submit/?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/05/13/demos-teched-dat305-best-practices-for-exception-handling-and-defensive-programming-in-microsoft-sql-server.aspx&amp;amp;title=Demos+-+TechEd+DAT305+-+Best+Practices+for+Exception+Handling+and+Defensive+Programming+in+Microsoft+SQL+Server" target="_blank" title = "Submit Demos - TechEd DAT305 - Best Practices for Exception Handling and Defensive Programming in Microsoft SQL Server to DotNetKicks"&gt;kick it!&lt;/a&gt; |  &lt;a href = "https://favorites.live.com/quickadd.aspx?marklet=1&amp;amp;mkt=en-us&amp;amp;url=http://sqlblog.com/blogs/adam_machanic/archive/2009/05/13/demos-teched-dat305-best-practices-for-exception-handling-and-defensive-programming-in-microsoft-sql-server.aspx&amp;amp;title=Demos+-+TechEd+DAT305+-+Best+Practices+for+Exception+Handling+and+Defensive+Programming+in+Microsoft+SQL+Server&amp;amp;;top=1" target="_blank" title = "Add Demos - TechEd DAT305 - Best Practices for Exception Handling and Defensive Programming in Microsoft SQL Server to Live Bookmarks"&gt;live it!&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;img src="http://info.sqlblog.com/a.aspx?ZoneID=0&amp;BannerID=12&amp;AdvertiserID=1&amp;CampaignID=12&amp;Task=Get&amp;Mode=TEXT&amp;SiteID=1&amp;RandomNumber=463323" width="1" height="1" border="0"&gt;&lt;img src="http://sqlblog.com/aggbug.aspx?PostID=14030" width="1" height="1"&gt;</description><enclosure url="http://sqlblog.com/blogs/adam_machanic/attachment/14030.ashx" length="3592" type="application/x-zip-compressed" /><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/errors/default.aspx">errors</category><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/exception+handling/default.aspx">exception handling</category><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/TechEd/default.aspx">TechEd</category></item><item><title>I Swallowed the Twitter-Colored Pill</title><link>http://sqlblog.com/blogs/adam_machanic/archive/2009/05/06/i-swallowed-the-twitter-colored-pill.aspx</link><pubDate>Thu, 07 May 2009 01:14:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:13838</guid><dc:creator>Adam Machanic</dc:creator><slash:comments>10</slash:comments><comments>http://sqlblog.com/blogs/adam_machanic/comments/13838.aspx</comments><wfw:commentRss>http://sqlblog.com/blogs/adam_machanic/commentrss.aspx?PostID=13838</wfw:commentRss><description>&lt;p&gt;I'm not entirely certain what color that is, but &lt;a href="http://twitter.com/AdamMachanic"&gt;follow me here (if you dare)&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;In keeping with the Twitter mentality I'll keep this post ultra-short.&lt;br&gt;&lt;/p&gt;
&lt;BR&gt;&lt;div class = "shareblock"&gt;&lt;span class = "shareblockTitle"&gt;Share this post:&lt;/span&gt;&lt;span class = "shareblockLink"&gt; &lt;a href = "mailto:?subject=I Swallowed the Twitter-Colored Pill&amp;amp;body=Seen on SQLblog.com: %0A%0A%09I Swallowed the Twitter-Colored Pill%0A%0Ahttp://sqlblog.com/blogs/adam_machanic/archive/2009/05/06/i-swallowed-the-twitter-colored-pill.aspx" target="_blank" title = "Email I Swallowed the Twitter-Colored Pill"&gt;email it!&lt;/a&gt; |  &lt;a href = "http://del.icio.us/post?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/05/06/i-swallowed-the-twitter-colored-pill.aspx&amp;amp;title=I+Swallowed+the+Twitter-Colored+Pill" target="_blank" title = "Submit I Swallowed the Twitter-Colored Pill to del.icio.us"&gt;bookmark it!&lt;/a&gt; |  &lt;a href = "http://www.digg.com/submit?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/05/06/i-swallowed-the-twitter-colored-pill.aspx&amp;amp;phase=2" target="_blank" title = "Submit I Swallowed the Twitter-Colored Pill to digg.com"&gt;digg it!&lt;/a&gt; |  &lt;a href = "http://reddit.com/submit?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/05/06/i-swallowed-the-twitter-colored-pill.aspx&amp;amp;title=I+Swallowed+the+Twitter-Colored+Pill" target="_blank" title = "Submit I Swallowed the Twitter-Colored Pill to reddit.com"&gt;reddit!&lt;/a&gt; |  &lt;a href = "http://www.dotnetkicks.com/submit/?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/05/06/i-swallowed-the-twitter-colored-pill.aspx&amp;amp;title=I+Swallowed+the+Twitter-Colored+Pill" target="_blank" title = "Submit I Swallowed the Twitter-Colored Pill to DotNetKicks"&gt;kick it!&lt;/a&gt; |  &lt;a href = "https://favorites.live.com/quickadd.aspx?marklet=1&amp;amp;mkt=en-us&amp;amp;url=http://sqlblog.com/blogs/adam_machanic/archive/2009/05/06/i-swallowed-the-twitter-colored-pill.aspx&amp;amp;title=I+Swallowed+the+Twitter-Colored+Pill&amp;amp;;top=1" target="_blank" title = "Add I Swallowed the Twitter-Colored Pill to Live Bookmarks"&gt;live it!&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;img src="http://info.sqlblog.com/a.aspx?ZoneID=0&amp;BannerID=12&amp;AdvertiserID=1&amp;CampaignID=12&amp;Task=Get&amp;Mode=TEXT&amp;SiteID=1&amp;RandomNumber=463323" width="1" height="1" border="0"&gt;&lt;img src="http://sqlblog.com/aggbug.aspx?PostID=13838" width="1" height="1"&gt;</description><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/twitter/default.aspx">twitter</category></item><item><title>SQLCLR String Splitting Part 2: Even Faster, Even More Scalable</title><link>http://sqlblog.com/blogs/adam_machanic/archive/2009/04/28/sqlclr-string-splitting-part-2-even-faster-even-more-scalable.aspx</link><pubDate>Tue, 28 Apr 2009 18:54:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:13612</guid><dc:creator>Adam Machanic</dc:creator><slash:comments>4</slash:comments><comments>http://sqlblog.com/blogs/adam_machanic/comments/13612.aspx</comments><wfw:commentRss>http://sqlblog.com/blogs/adam_machanic/commentrss.aspx?PostID=13612</wfw:commentRss><description>
&lt;p&gt;Two days ago, after posting what I thought was &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2009/04/26/faster-more-scalable-sqlclr-string-splitting.aspx"&gt;a pretty solid SQLCLR string splitting method&lt;/a&gt;, I received a comment telling me about a &lt;a href="http://www.sqlservercentral.com/Forums/Topic695508-338-1.aspx?Update=1"&gt;big thread on SQLServerCentral&lt;/a&gt; dedicated to the question of how best to split strings. So I jumped in, and went back and forth, and back and forth, and back... and forth... &lt;/p&gt;
&lt;p&gt;Many, many messages and several revisions and re-revisions later, I am happy to present the newer, better, more bug-free SQLCLR string splitting function. Not only is it faster than the previous one I posted, but it also handles multi-character delimiters, ignores consecutive delimiters as well as pre and post delimiters, and best of all, it won't get itself stuck in an infinite loop in certain cases (always a really great stability feature).&lt;/p&gt;
&lt;p&gt;This version walks the SqlChars character array rather than using the IndexOf method on the string, which we found to be a somewhat faster technique--and it's certainly the most scalable and memory efficient method I can imagine. &lt;/p&gt;
&lt;p&gt;Special thanks to SQLServerCentral member Florian Reischl, who was the main person keeping the thread going with me during the last couple of days, and who managed to re-write my versions and eke out even better performance by modifying the algorithms.&amp;nbsp; Great stuff--it was definitely the most fun I've had on a technical forum in quite a long time.&lt;/p&gt;
&lt;p&gt;But without further ado, the code:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;p&gt;using System;&lt;br&gt;using System.Collections;&lt;br&gt;using System.Data;&lt;br&gt;using System.Data.SqlClient;&lt;br&gt;using System.Data.SqlTypes;&lt;br&gt;using Microsoft.SqlServer.Server;&lt;br&gt;&lt;br&gt;public partial class UserDefinedFunctions&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Microsoft.SqlServer.Server.SqlFunction(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FillRowMethodName = "FillRow_Multi",&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; TableDefinition = "item nvarchar(4000)"&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static IEnumerator SplitString_Multi(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [SqlFacet(MaxSize = -1)]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SqlChars Input,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [SqlFacet(MaxSize = 255)]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SqlChars Delimiter&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return (&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (Input.IsNull || Delimiter.IsNull) ?&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new SplitStringMulti(new char[0], new char[0]) :&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new SplitStringMulti(Input.Value, Delimiter.Value));&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static void FillRow_Multi(object obj, out SqlString item)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; item = new SqlString((string)obj);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class SplitStringMulti : IEnumerator&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public SplitStringMulti(char[] TheString, char[] Delimiter)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; theString = TheString;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; stringLen = TheString.Length;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; delimiter = Delimiter;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; delimiterLen = (byte)(Delimiter.Length);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; isSingleCharDelim = (delimiterLen == 1);&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lastPos = 0;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; nextPos = delimiterLen * -1;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; #region IEnumerator Members&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public object Current&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return new string(theString, lastPos, nextPos - lastPos);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public bool MoveNext()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (nextPos &amp;gt;= stringLen)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lastPos = nextPos + delimiterLen;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (int i = lastPos; i &amp;lt; stringLen; i++)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; bool matches = true;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Optimize for single-character delimiters&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (isSingleCharDelim)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (theString[i] != delimiter[0])&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; matches = false;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (byte j = 0; j &amp;lt; delimiterLen; j++)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (((i + j) &amp;gt;= stringLen) || (theString[i + j] != delimiter[j]))&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; matches = false;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (matches)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; nextPos = i;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Deal with consecutive delimiters&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ((nextPos - lastPos) &amp;gt; 0)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return true;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; i += (delimiterLen-1);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lastPos += delimiterLen;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lastPos = nextPos + delimiterLen;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; nextPos = stringLen;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ((nextPos - lastPos) &amp;gt; 0)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return true;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void Reset()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lastPos = 0;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; nextPos = delimiterLen * -1;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; #endregion&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private int lastPos;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private int nextPos;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly char[] theString;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly char[] delimiter;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly int stringLen;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly byte delimiterLen;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly bool isSingleCharDelim;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;};&lt;/p&gt;
&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;Enjoy! &lt;br&gt;&lt;/p&gt;
&lt;BR&gt;&lt;div class = "shareblock"&gt;&lt;span class = "shareblockTitle"&gt;Share this post:&lt;/span&gt;&lt;span class = "shareblockLink"&gt; &lt;a href = "mailto:?subject=SQLCLR String Splitting Part 2: Even Faster, Even More Scalable&amp;amp;body=Seen on SQLblog.com: %0A%0A%09SQLCLR String Splitting Part 2: Even Faster, Even More Scalable%0A%0Ahttp://sqlblog.com/blogs/adam_machanic/archive/2009/04/28/sqlclr-string-splitting-part-2-even-faster-even-more-scalable.aspx" target="_blank" title = "Email SQLCLR String Splitting Part 2: Even Faster, Even More Scalable"&gt;email it!&lt;/a&gt; |  &lt;a href = "http://del.icio.us/post?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/04/28/sqlclr-string-splitting-part-2-even-faster-even-more-scalable.aspx&amp;amp;title=SQLCLR+String+Splitting+Part+2%3a+Even+Faster%2c+Even+More+Scalable" target="_blank" title = "Submit SQLCLR String Splitting Part 2: Even Faster, Even More Scalable to del.icio.us"&gt;bookmark it!&lt;/a&gt; |  &lt;a href = "http://www.digg.com/submit?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/04/28/sqlclr-string-splitting-part-2-even-faster-even-more-scalable.aspx&amp;amp;phase=2" target="_blank" title = "Submit SQLCLR String Splitting Part 2: Even Faster, Even More Scalable to digg.com"&gt;digg it!&lt;/a&gt; |  &lt;a href = "http://reddit.com/submit?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/04/28/sqlclr-string-splitting-part-2-even-faster-even-more-scalable.aspx&amp;amp;title=SQLCLR+String+Splitting+Part+2%3a+Even+Faster%2c+Even+More+Scalable" target="_blank" title = "Submit SQLCLR String Splitting Part 2: Even Faster, Even More Scalable to reddit.com"&gt;reddit!&lt;/a&gt; |  &lt;a href = "http://www.dotnetkicks.com/submit/?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/04/28/sqlclr-string-splitting-part-2-even-faster-even-more-scalable.aspx&amp;amp;title=SQLCLR+String+Splitting+Part+2%3a+Even+Faster%2c+Even+More+Scalable" target="_blank" title = "Submit SQLCLR String Splitting Part 2: Even Faster, Even More Scalable to DotNetKicks"&gt;kick it!&lt;/a&gt; |  &lt;a href = "https://favorites.live.com/quickadd.aspx?marklet=1&amp;amp;mkt=en-us&amp;amp;url=http://sqlblog.com/blogs/adam_machanic/archive/2009/04/28/sqlclr-string-splitting-part-2-even-faster-even-more-scalable.aspx&amp;amp;title=SQLCLR+String+Splitting+Part+2%3a+Even+Faster%2c+Even+More+Scalable&amp;amp;;top=1" target="_blank" title = "Add SQLCLR String Splitting Part 2: Even Faster, Even More Scalable to Live Bookmarks"&gt;live it!&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;img src="http://info.sqlblog.com/a.aspx?ZoneID=0&amp;BannerID=12&amp;AdvertiserID=1&amp;CampaignID=12&amp;Task=Get&amp;Mode=TEXT&amp;SiteID=1&amp;RandomNumber=463323" width="1" height="1" border="0"&gt;&lt;img src="http://sqlblog.com/aggbug.aspx?PostID=13612" width="1" height="1"&gt;</description><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/Performance/default.aspx">Performance</category><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/SQLCLR/default.aspx">SQLCLR</category><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/string+splitting/default.aspx">string splitting</category></item><item><title>Faster, More Scalable SQLCLR String Splitting</title><link>http://sqlblog.com/blogs/adam_machanic/archive/2009/04/26/faster-more-scalable-sqlclr-string-splitting.aspx</link><pubDate>Sun, 26 Apr 2009 23:59:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:13570</guid><dc:creator>Adam Machanic</dc:creator><slash:comments>13</slash:comments><comments>http://sqlblog.com/blogs/adam_machanic/comments/13570.aspx</comments><wfw:commentRss>http://sqlblog.com/blogs/adam_machanic/commentrss.aspx?PostID=13570</wfw:commentRss><description>&lt;p&gt;It seems like every couple of months we see yet another post on SQLCLR string splitting routines. Many bloggers, I suppose, are still struggling, even three years later, to find that "perfect" use case for SQLCLR. Is string splitting it? Probably not. And with SQL Server 2008 table-valued parameters now available, SQLCLR string splitting has become an even less interesting exercise than it was before. None the less, a recent post on the &lt;a href="http://blogs.lessthandot.com/index.php/DataMgmt/DBProgramming/split-string-in-sql-server-2005-clr-vs-t"&gt;Less Than Dot&lt;/a&gt; site has inspired me to counter with my own best SQLCLR string splitting method, for those of you who are still interested in solving this problem.&lt;br&gt;&lt;/p&gt;

&lt;p&gt;I've noticed that almost invariably, the methods posted online stress how very &lt;span style="font-style:italic;"&gt;easy &lt;/span&gt;it is to do string splitting in .NET, thanks to the String.Split method. And while this easy method tends to work pretty well for small strings and on workloads that don't need to scale, it quickly breaks down when any amount of load is introduced (something that, unfortunately, most writers don't bother considering). The Less Than Dot writer, "onpnt" did do some testing, and discovered that--surprise, surprise--String.Split isn't all that great.&lt;br&gt;&lt;/p&gt;

&lt;p&gt;The issue? Well, it all comes down to large memory allocations and the art of scalable .NET programming--an area about which many SQL Server developers can (and do) remain blissfully naïve. In .NET, reduction of memory utilization--especially large allocation done en masse--is king, and String.Split does exactly the wrong thing. It takes the input string, breaks it into N chunks, and allocates all of the memory needed to store those chunks and pointers to those chunks, in one big huge operation. This can't possibly scale, and indeed it doesn't.&amp;nbsp; I did a quick &lt;a href="http://datamanipulation.net/sqlquerystress/"&gt;SQLQueryStress&lt;/a&gt; test of a TVF based on String.Split and saw fairly good performance when the input sentences were small (in the 40-400 byte range--see below), but after a certain point the AppDomains began recycling and performance became abysmal. Protections put in place for stability of the CLR host include memory leak detection, and this kicks in quite readily when we force allocation of so much memory in one shot--a good thing for the SQL Server instance as a whole, but not great when we're trying to really split a huge string.&lt;br&gt;&lt;/p&gt;

&lt;p&gt;Students of .NET who are concerned with scale (and really, everyone should be) are urged to look at the way problems are handled in LINQ. Here the vast majority of requests are internally handled using streaming iterator patterns, rather than moving around huge chunks of memory. This turns out to a much more scalable option for several reasons: Lower in-flight memory utilization, fewer large object heap allocations, and better access by the garbage collector to collect intermediate data that is no longer needed.&lt;/p&gt;

&lt;p&gt;So how can we apply streaming to the string splitting problem? Rather than break the string up into all of its component parts upfront, we can walk the string step-by-step, only finding the next piece as required. In order to handle this, I created the following worker class:&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class splitIt : IEnumerator&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public splitIt(string theString, char delimiter)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.theString = theString;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.delimiter = delimiter;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.lastPos = -1;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.nextPos = -1;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; #region IEnumerator Members&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public object Current&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get { return theString.Substring(lastPos, nextPos - lastPos).Trim(); }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public bool MoveNext()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (nextPos &amp;gt;= theString.Length)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lastPos = nextPos + 1;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (lastPos == theString.Length)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; nextPos = theString.IndexOf(delimiter, lastPos);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (nextPos == -1)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; nextPos = theString.Length;&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return true;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void Reset()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.lastPos = -1;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.nextPos = -1;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; #endregion&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private int lastPos;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private int nextPos;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private string theString;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private char delimiter;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;br&gt;&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;
This class is a simple enumerator implementation that looks for the next delimiter on each iteration, only when requested. Splitting strings in this way, rather than using String.Split, means that no huge upfront allocation takes place. Aside from the sentence itself, only one "chunk" is in play at any given time, and any chunks that have already been used can be garbage collected as needed when memory is tight. &lt;br&gt;&lt;/p&gt;
&lt;p&gt;Wiring this class up in a SQLCR TVF is just about as simple as when using String.Split:&lt;/p&gt;
&lt;pre&gt;&lt;p style="margin-left:40px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Microsoft.SqlServer.Server.SqlFunction(FillRowMethodName = "FillIt", TableDefinition = "output nvarchar(4000)")]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static IEnumerator faster_split&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SqlChars instr, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [SqlFacet(IsFixedLength=true, MaxSize=1)]&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SqlString delimiter&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return (&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (instr.IsNull || delimiter.IsNull) ? &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new splitIt("", ',') : &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new splitIt(instr.ToSqlString().Value, Convert.ToChar(delimiter.Value)));&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static void FillIt(object obj, out SqlString output)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; output = (new SqlString((string)obj));&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;/pre&gt;
&lt;p&gt;I've enhanced this example slightly compared with most of the usual suspects: A SqlFacet attribute is used to make sure that the delimiter is only a single character, and I've added a bit of additional code in the main method to deal with NULL inputs.&lt;/p&gt;&lt;p&gt;The scalability difference between this method and the String.Split method is staggering in the simple tests I ran today on my SQL Server 2008 test server.&amp;nbsp; With small sentences, even under moderate load (100 concurrent threads), each method performs more or less equivalently.&amp;nbsp; But as sentence size increases to 50KB, the String.Split method begins slowing, taking almost 2 seconds per iteration, and the occasional AppDomain recycle is seen in the SQL Server log.&amp;nbsp; The streaming method, on the other hand, continues to complete its job in just over 1/10th of a second, and causes no AppDomain recycles. Increasing to 500KB sentences, String.Split causes numerous AppDomain recycles and time per iteration increases to over 30 seconds, while the streaming method averages just 16 seconds per iteration. Jumping to 5MB sentences, String.Split causes almost continuous AppDomain recycles, and each iteration takes almost 6 &lt;span style="font-style:italic;"&gt;minutes &lt;/span&gt;to complete. Yet with the streaming method, even with sentences of this size I am still unable to cause an AppDomain recycle to occur, and iterations complete in around 55 seconds. &lt;/p&gt;&lt;p&gt;The test I did was quite simple, and I won't post too many details here as I prefer that you test with your own workloads and draw your own conclusion about how this method fares when compared with T-SQL versions or the naïve String.Split method. I hope that if you do test you'll post back here with your results so that we can all learn the best way to handle these problems--whether or not string splitting really is all that interesting in the post-SQL Server 2005 world.&lt;br&gt;&lt;/p&gt;
&lt;BR&gt;&lt;div class = "shareblock"&gt;&lt;span class = "shareblockTitle"&gt;Share this post:&lt;/span&gt;&lt;span class = "shareblockLink"&gt; &lt;a href = "mailto:?subject=Faster, More Scalable SQLCLR String Splitting&amp;amp;body=Seen on SQLblog.com: %0A%0A%09Faster, More Scalable SQLCLR String Splitting%0A%0Ahttp://sqlblog.com/blogs/adam_machanic/archive/2009/04/26/faster-more-scalable-sqlclr-string-splitting.aspx" target="_blank" title = "Email Faster, More Scalable SQLCLR String Splitting"&gt;email it!&lt;/a&gt; |  &lt;a href = "http://del.icio.us/post?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/04/26/faster-more-scalable-sqlclr-string-splitting.aspx&amp;amp;title=Faster%2c+More+Scalable+SQLCLR+String+Splitting" target="_blank" title = "Submit Faster, More Scalable SQLCLR String Splitting to del.icio.us"&gt;bookmark it!&lt;/a&gt; |  &lt;a href = "http://www.digg.com/submit?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/04/26/faster-more-scalable-sqlclr-string-splitting.aspx&amp;amp;phase=2" target="_blank" title = "Submit Faster, More Scalable SQLCLR String Splitting to digg.com"&gt;digg it!&lt;/a&gt; |  &lt;a href = "http://reddit.com/submit?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/04/26/faster-more-scalable-sqlclr-string-splitting.aspx&amp;amp;title=Faster%2c+More+Scalable+SQLCLR+String+Splitting" target="_blank" title = "Submit Faster, More Scalable SQLCLR String Splitting to reddit.com"&gt;reddit!&lt;/a&gt; |  &lt;a href = "http://www.dotnetkicks.com/submit/?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/04/26/faster-more-scalable-sqlclr-string-splitting.aspx&amp;amp;title=Faster%2c+More+Scalable+SQLCLR+String+Splitting" target="_blank" title = "Submit Faster, More Scalable SQLCLR String Splitting to DotNetKicks"&gt;kick it!&lt;/a&gt; |  &lt;a href = "https://favorites.live.com/quickadd.aspx?marklet=1&amp;amp;mkt=en-us&amp;amp;url=http://sqlblog.com/blogs/adam_machanic/archive/2009/04/26/faster-more-scalable-sqlclr-string-splitting.aspx&amp;amp;title=Faster%2c+More+Scalable+SQLCLR+String+Splitting&amp;amp;;top=1" target="_blank" title = "Add Faster, More Scalable SQLCLR String Splitting to Live Bookmarks"&gt;live it!&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;img src="http://info.sqlblog.com/a.aspx?ZoneID=0&amp;BannerID=12&amp;AdvertiserID=1&amp;CampaignID=12&amp;Task=Get&amp;Mode=TEXT&amp;SiteID=1&amp;RandomNumber=463323" width="1" height="1" border="0"&gt;&lt;img src="http://sqlblog.com/aggbug.aspx?PostID=13570" width="1" height="1"&gt;</description><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/Performance/default.aspx">Performance</category><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/SQLCLR/default.aspx">SQLCLR</category><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/string+splitting/default.aspx">string splitting</category><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/scalability/default.aspx">scalability</category></item><item><title>Do You Change the Results to Grid Font in SSMS?</title><link>http://sqlblog.com/blogs/adam_machanic/archive/2009/04/24/do-you-change-the-results-to-grid-font-in-ssms.aspx</link><pubDate>Fri, 24 Apr 2009 20:28:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:13510</guid><dc:creator>Adam Machanic</dc:creator><slash:comments>13</slash:comments><comments>http://sqlblog.com/blogs/adam_machanic/comments/13510.aspx</comments><wfw:commentRss>http://sqlblog.com/blogs/adam_machanic/commentrss.aspx?PostID=13510</wfw:commentRss><description>&lt;p&gt;&lt;b&gt;Update: Please &lt;a href="http://sqlblog.com/forums/13518/ShowThread.aspx#13518"&gt;respond here instead&lt;/a&gt;.&amp;nbsp; Thanks for the great idea, Alex!&lt;/b&gt; &lt;br&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Please respond and let me know:&lt;/p&gt;&lt;p&gt;A) Whether you change it at all &lt;br&gt;&lt;/p&gt;&lt;p&gt;and &lt;/p&gt;&lt;p&gt;B) If so, whether you use a fixed width font (the default font is non-fixed width)&lt;/p&gt;&lt;p&gt;Background, in case you're curious: I modified a newer version of &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2009/03/30/who-is-active-v8-40-now-with-delta-power.aspx"&gt;Who is Active?&lt;/a&gt;, based on some feedback I received from &lt;a href="http://sqlblog.com/blogs/aaron_bertrand/"&gt;Aaron Bertrand&lt;/a&gt; asking for right-padding of the numbers in the result.&amp;nbsp; I did this modification based on my assumption that most people won't change the default grid font, and even if they do change it they'll still use a non-fixed width font.&amp;nbsp; I tested my modification on my end and sent it over to Aaron to see what he thought, and low and behold he has changed his own SSMS settings to use a fixed width font.&amp;nbsp; Oops!&amp;nbsp; I would be very interested in finding out how many of you do the same.&amp;nbsp; If the vast majority of people do indeed leave the font unchanged, or at least in the same font family, perhaps I'll leave the right-padding as-is (I happen to like it, personally -- sorry, Aaron!).&amp;nbsp; If I'm mistaken in my assumption, I'll rip it out.&lt;/p&gt;&lt;p&gt;Thanks for letting me know, either way. &lt;br&gt;&lt;/p&gt;
&lt;BR&gt;&lt;div class = "shareblock"&gt;&lt;span class = "shareblockTitle"&gt;Share this post:&lt;/span&gt;&lt;span class = "shareblockLink"&gt; &lt;a href = "mailto:?subject=Do You Change the Results to Grid Font in SSMS?&amp;amp;body=Seen on SQLblog.com: %0A%0A%09Do You Change the Results to Grid Font in SSMS?%0A%0Ahttp://sqlblog.com/blogs/adam_machanic/archive/2009/04/24/do-you-change-the-results-to-grid-font-in-ssms.aspx" target="_blank" title = "Email Do You Change the Results to Grid Font in SSMS?"&gt;email it!&lt;/a&gt; |  &lt;a href = "http://del.icio.us/post?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/04/24/do-you-change-the-results-to-grid-font-in-ssms.aspx&amp;amp;title=Do+You+Change+the+Results+to+Grid+Font+in+SSMS%3f" target="_blank" title = "Submit Do You Change the Results to Grid Font in SSMS? to del.icio.us"&gt;bookmark it!&lt;/a&gt; |  &lt;a href = "http://www.digg.com/submit?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/04/24/do-you-change-the-results-to-grid-font-in-ssms.aspx&amp;amp;phase=2" target="_blank" title = "Submit Do You Change the Results to Grid Font in SSMS? to digg.com"&gt;digg it!&lt;/a&gt; |  &lt;a href = "http://reddit.com/submit?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/04/24/do-you-change-the-results-to-grid-font-in-ssms.aspx&amp;amp;title=Do+You+Change+the+Results+to+Grid+Font+in+SSMS%3f" target="_blank" title = "Submit Do You Change the Results to Grid Font in SSMS? to reddit.com"&gt;reddit!&lt;/a&gt; |  &lt;a href = "http://www.dotnetkicks.com/submit/?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/04/24/do-you-change-the-results-to-grid-font-in-ssms.aspx&amp;amp;title=Do+You+Change+the+Results+to+Grid+Font+in+SSMS%3f" target="_blank" title = "Submit Do You Change the Results to Grid Font in SSMS? to DotNetKicks"&gt;kick it!&lt;/a&gt; |  &lt;a href = "https://favorites.live.com/quickadd.aspx?marklet=1&amp;amp;mkt=en-us&amp;amp;url=http://sqlblog.com/blogs/adam_machanic/archive/2009/04/24/do-you-change-the-results-to-grid-font-in-ssms.aspx&amp;amp;title=Do+You+Change+the+Results+to+Grid+Font+in+SSMS%3f&amp;amp;;top=1" target="_blank" title = "Add Do You Change the Results to Grid Font in SSMS? to Live Bookmarks"&gt;live it!&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;img src="http://info.sqlblog.com/a.aspx?ZoneID=0&amp;BannerID=12&amp;AdvertiserID=1&amp;CampaignID=12&amp;Task=Get&amp;Mode=TEXT&amp;SiteID=1&amp;RandomNumber=463323" width="1" height="1" border="0"&gt;&lt;img src="http://sqlblog.com/aggbug.aspx?PostID=13510" width="1" height="1"&gt;</description><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/who+is+active/default.aspx">who is active</category><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/ssms/default.aspx">ssms</category><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/fonts/default.aspx">fonts</category></item><item><title>TechEd Coming Up - Recommended Background for My Extended Events Talk</title><link>http://sqlblog.com/blogs/adam_machanic/archive/2009/04/22/teched-coming-up-recommend-background-for-my-extended-events-talk.aspx</link><pubDate>Thu, 23 Apr 2009 01:46:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:13465</guid><dc:creator>Adam Machanic</dc:creator><slash:comments>4</slash:comments><comments>http://sqlblog.com/blogs/adam_machanic/comments/13465.aspx</comments><wfw:commentRss>http://sqlblog.com/blogs/adam_machanic/commentrss.aspx?PostID=13465</wfw:commentRss><description>&lt;p&gt;TechEd North America 2009 is just a few short weeks away, and I'm really looking forward not only to the show, but also the opportunity to visit Los Angeles for the first time in several years.&amp;nbsp; I'm busy putting the finishing touches on my Extended Events talk, DAT402, "Microsoft SQL Server 2008: Performance Profiling and Troubleshooting with Extended Events", and I thought I should write a quick note to anyone out there who is thinking of attending.&amp;nbsp; &lt;/p&gt;&lt;p&gt;What's noteworthy about this talk is that the TechEd team modified the title a bit and removed the word "Advanced", but left the talk at 400-level and also left the original abstract untouched:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Imagine tracking and aggregating wait statistics at the session level
rather than the server level. Imagine seeing exactly how long each step
in your query took and figuring out the real cost of that index scan.
Imagine capturing an exception with an associated callstack--no more
guessing about exactly what component failed and why. When you're done
imagining, open your eyes and attend this session to learn all of these
techniques and more, all thanks to Extended Events (XEvents)--the
powerful new tracing infrastructure in SQL Server 2008. Designed for
DBAs and developers who already understand the basics of XEvents, this
session goes from 0 to 60 in the first few minutes. See a number of
code examples and gain an understanding of how to maximize XEvents for
performance profiling and troubleshooting purposes. If you're serious
about making your SQL Servers fly, this is one session not to be missed.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;When I gave this same talk earlier this year at SQL Server Connections in Orlando, some attendees apparently didn't understand that it really is an advanced talk, and showed up without quite enough background to follow along as well as they could have.&amp;nbsp; I'm hoping to minimize that phenomenon at TechEd; so please keep in mind that although I do a quick (five-minute) refresher, that's it, and Extended Events is a much bigger topic than can be fully introduced in five minutes.&amp;nbsp; Once the refresher part is over I jump into four fairly intense, demo-heavy deep-dive sections, so please, if you want to get your money's worth, make sure that you read one or more of the following in the next few weeks:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;My chapter in the &lt;a href="http://www.amazon.com/Microsoft%C2%AE-SQL-Server%C2%AE-2008-Internals/dp/0735626243"&gt;SQL Server 2008 Internals&lt;/a&gt; book&lt;/li&gt;&lt;li&gt;The Extended Events section in the recently-released &lt;a href="http://msdn.microsoft.com/en-us/library/dd672789.aspx" target="_blank"&gt;Troubleshooting Performance Problems in SQL Server 2008&lt;/a&gt; white paper&lt;/li&gt;&lt;li&gt;Paul Randal's &lt;a href="http://technet.microsoft.com/en-us/magazine/dd314391.aspx"&gt;Advanced Troubleshooting with Extended Events&lt;/a&gt; article in TechNet Magazine&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Reading through these sources will give you the background so that you can focus on the performance troubleshooting aspects of the talk, rather than sitting there bogged down in the unfamiliar Extended Events syntax and terminology. &lt;br&gt;&lt;/p&gt;&lt;p&gt;I'm looking forward to meeting some SQLblog readers at the event; if you're attending, even if you decide to skip my Extended Events talk, stop by the Database Practices TLC and say hi.&amp;nbsp; Looking forward to seeing you in LA!&lt;br&gt;&lt;/p&gt;
&lt;BR&gt;&lt;div class = "shareblock"&gt;&lt;span class = "shareblockTitle"&gt;Share this post:&lt;/span&gt;&lt;span class = "shareblockLink"&gt; &lt;a href = "mailto:?subject=TechEd Coming Up - Recommended Background for My Extended Events Talk&amp;amp;body=Seen on SQLblog.com: %0A%0A%09TechEd Coming Up - Recommended Background for My Extended Events Talk%0A%0Ahttp://sqlblog.com/blogs/adam_machanic/archive/2009/04/22/teched-coming-up-recommend-background-for-my-extended-events-talk.aspx" target="_blank" title = "Email TechEd Coming Up - Recommended Background for My Extended Events Talk"&gt;email it!&lt;/a&gt; |  &lt;a href = "http://del.icio.us/post?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/04/22/teched-coming-up-recommend-background-for-my-extended-events-talk.aspx&amp;amp;title=TechEd+Coming+Up+-+Recommended+Background+for+My+Extended+Events+Talk" target="_blank" title = "Submit TechEd Coming Up - Recommended Background for My Extended Events Talk to del.icio.us"&gt;bookmark it!&lt;/a&gt; |  &lt;a href = "http://www.digg.com/submit?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/04/22/teched-coming-up-recommend-background-for-my-extended-events-talk.aspx&amp;amp;phase=2" target="_blank" title = "Submit TechEd Coming Up - Recommended Background for My Extended Events Talk to digg.com"&gt;digg it!&lt;/a&gt; |  &lt;a href = "http://reddit.com/submit?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/04/22/teched-coming-up-recommend-background-for-my-extended-events-talk.aspx&amp;amp;title=TechEd+Coming+Up+-+Recommended+Background+for+My+Extended+Events+Talk" target="_blank" title = "Submit TechEd Coming Up - Recommended Background for My Extended Events Talk to reddit.com"&gt;reddit!&lt;/a&gt; |  &lt;a href = "http://www.dotnetkicks.com/submit/?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/04/22/teched-coming-up-recommend-background-for-my-extended-events-talk.aspx&amp;amp;title=TechEd+Coming+Up+-+Recommended+Background+for+My+Extended+Events+Talk" target="_blank" title = "Submit TechEd Coming Up - Recommended Background for My Extended Events Talk to DotNetKicks"&gt;kick it!&lt;/a&gt; |  &lt;a href = "https://favorites.live.com/quickadd.aspx?marklet=1&amp;amp;mkt=en-us&amp;amp;url=http://sqlblog.com/blogs/adam_machanic/archive/2009/04/22/teched-coming-up-recommend-background-for-my-extended-events-talk.aspx&amp;amp;title=TechEd+Coming+Up+-+Recommended+Background+for+My+Extended+Events+Talk&amp;amp;;top=1" target="_blank" title = "Add TechEd Coming Up - Recommended Background for My Extended Events Talk to Live Bookmarks"&gt;live it!&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;img src="http://info.sqlblog.com/a.aspx?ZoneID=0&amp;BannerID=12&amp;AdvertiserID=1&amp;CampaignID=12&amp;Task=Get&amp;Mode=TEXT&amp;SiteID=1&amp;RandomNumber=463323" width="1" height="1" border="0"&gt;&lt;img src="http://sqlblog.com/aggbug.aspx?PostID=13465" width="1" height="1"&gt;</description><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/TechEd/default.aspx">TechEd</category><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/extended+events/default.aspx">extended events</category></item><item><title>Connect Item: Globally-Scoped Metadata Views</title><link>http://sqlblog.com/blogs/adam_machanic/archive/2009/04/16/connect-item-globally-scoped-metadata-views.aspx</link><pubDate>Thu, 16 Apr 2009 15:09:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:13328</guid><dc:creator>Adam Machanic</dc:creator><slash:comments>4</slash:comments><comments>http://sqlblog.com/blogs/adam_machanic/comments/13328.aspx</comments><wfw:commentRss>http://sqlblog.com/blogs/adam_machanic/commentrss.aspx?PostID=13328</wfw:commentRss><description>&lt;p&gt;Ever tried writing a more or less database-agnostic administrative script?&lt;br&gt;&lt;/p&gt;&lt;p&gt;If the experience didn't make your head spin, you either have a stronger constitution than most DBAs or your script doesn't actually work properly. The fact is, due to the way most of the metadata views are currently scoped in SQL Server, pulling data from multiple databases requires a rather annoying set of techniques, usually involving temporary tables, dynamic SQL, and cursors. For a real-world example, just take a look at &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2009/03/30/who-is-active-v8-40-now-with-delta-power.aspx"&gt;my Who is Active? script&lt;/a&gt;.&lt;br&gt;&lt;/p&gt;&lt;p&gt;This could all be so much easier if the product simply exposed global views, available from anywhere, and keyed with a database_id column. The views could be internally partitioned to ensure great performance if you only need data from a single database, yet still flexible enough to provide data across the entire server. I think this feature would make the overall administrative experience much nicer, so I've created a Connect item, and I hope that you will vote for it (5, of course!):&lt;/p&gt;&lt;p&gt;&lt;a href="http://connect.microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=432689"&gt;http://connect.microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=432689&lt;/a&gt; &lt;/p&gt;&lt;p&gt;Thanks for your support! &lt;br&gt;&lt;/p&gt;
&lt;BR&gt;&lt;div class = "shareblock"&gt;&lt;span class = "shareblockTitle"&gt;Share this post:&lt;/span&gt;&lt;span class = "shareblockLink"&gt; &lt;a href = "mailto:?subject=Connect Item: Globally-Scoped Metadata Views&amp;amp;body=Seen on SQLblog.com: %0A%0A%09Connect Item: Globally-Scoped Metadata Views%0A%0Ahttp://sqlblog.com/blogs/adam_machanic/archive/2009/04/16/connect-item-globally-scoped-metadata-views.aspx" target="_blank" title = "Email Connect Item: Globally-Scoped Metadata Views"&gt;email it!&lt;/a&gt; |  &lt;a href = "http://del.icio.us/post?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/04/16/connect-item-globally-scoped-metadata-views.aspx&amp;amp;title=Connect+Item%3a+Globally-Scoped+Metadata+Views" target="_blank" title = "Submit Connect Item: Globally-Scoped Metadata Views to del.icio.us"&gt;bookmark it!&lt;/a&gt; |  &lt;a href = "http://www.digg.com/submit?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/04/16/connect-item-globally-scoped-metadata-views.aspx&amp;amp;phase=2" target="_blank" title = "Submit Connect Item: Globally-Scoped Metadata Views to digg.com"&gt;digg it!&lt;/a&gt; |  &lt;a href = "http://reddit.com/submit?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/04/16/connect-item-globally-scoped-metadata-views.aspx&amp;amp;title=Connect+Item%3a+Globally-Scoped+Metadata+Views" target="_blank" title = "Submit Connect Item: Globally-Scoped Metadata Views to reddit.com"&gt;reddit!&lt;/a&gt; |  &lt;a href = "http://www.dotnetkicks.com/submit/?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/04/16/connect-item-globally-scoped-metadata-views.aspx&amp;amp;title=Connect+Item%3a+Globally-Scoped+Metadata+Views" target="_blank" title = "Submit Connect Item: Globally-Scoped Metadata Views to DotNetKicks"&gt;kick it!&lt;/a&gt; |  &lt;a href = "https://favorites.live.com/quickadd.aspx?marklet=1&amp;amp;mkt=en-us&amp;amp;url=http://sqlblog.com/blogs/adam_machanic/archive/2009/04/16/connect-item-globally-scoped-metadata-views.aspx&amp;amp;title=Connect+Item%3a+Globally-Scoped+Metadata+Views&amp;amp;;top=1" target="_blank" title = "Add Connect Item: Globally-Scoped Metadata Views to Live Bookmarks"&gt;live it!&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;img src="http://info.sqlblog.com/a.aspx?ZoneID=0&amp;BannerID=12&amp;AdvertiserID=1&amp;CampaignID=12&amp;Task=Get&amp;Mode=TEXT&amp;SiteID=1&amp;RandomNumber=463323" width="1" height="1" border="0"&gt;&lt;img src="http://sqlblog.com/aggbug.aspx?PostID=13328" width="1" height="1"&gt;</description><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/metadata/default.aspx">metadata</category></item><item><title>Who is Active? v8.40 - Now With Delta Power!</title><link>http://sqlblog.com/blogs/adam_machanic/archive/2009/03/30/who-is-active-v8-40-now-with-delta-power.aspx</link><pubDate>Mon, 30 Mar 2009 16:41:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:13006</guid><dc:creator>Adam Machanic</dc:creator><slash:comments>19</slash:comments><comments>http://sqlblog.com/blogs/adam_machanic/comments/13006.aspx</comments><wfw:commentRss>http://sqlblog.com/blogs/adam_machanic/commentrss.aspx?PostID=13006</wfw:commentRss><description>&lt;p&gt;It has been only a month and a half since I posted the last version of Who is Active? (&lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2009/02/18/who-is-active-v7-30.aspx"&gt;v7.30&lt;/a&gt;),
but in that time I've made a huge number of changes, fixes, and
enhancements. &lt;a href="http://sqlblog.com/blogs/adam_machanic/attachment/13006.ashx"&gt;The new version, v8.40&lt;/a&gt;, is faster, more robust, and
includes a few exciting features. &lt;/p&gt;&lt;p&gt;&lt;a href="http://sqlblog.com/blogs/adam_machanic/attachment/13006.ashx"&gt;&lt;b&gt;Click here to download Who is Active? v8.40&lt;/b&gt;&lt;/a&gt; &lt;br&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Following is a list of some of the
things I've done with it, in no particular order, along with
descriptions where applicable.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Added a &lt;b&gt;collection interval&lt;/b&gt;
option, @DELTA_INTERVAL. This option causes the script to collect
numeric metrics -- such as reads, writes, and context switches --
twice. The script will wait between collections, based on the duration
passed into the parameter (in seconds). The script will then calculate
the differences (deltas), between the first and second collections, for
any requests that were active for each collection. These deltas will be
output in a new set of columns, reads_delta, writes_delta,
context_switches_delta, etc.&lt;/p&gt;&lt;p&gt;For example, to use the default options and wait two seconds between collections, you would use the following:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;EXEC sp_WhoIsActive @DELTA_INTERVAL = 2;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;If
you played with Who is Active? in the past you know that the script
outputs a lot of data in a lot of different columns. I started feeling
that the column list was getting unwieldy, so I implemented &lt;b&gt;dynamic column lists&lt;/b&gt;
as a fix. There are two changes here. First of all, the default column
list will only contain columns associated with those features you have
turned on. So for example, if you don't have @GET_LOCKS enabled, the
locks column won't appear.&lt;/p&gt;&lt;p&gt;The second part of this fix is a new feature to make things even more dynamic: &lt;b&gt;custom column lists&lt;/b&gt;. I sent a slightly earlier test version to &lt;a href="http://blogs.msdn.com/jimmymay/"&gt;Jimmy May&lt;/a&gt;,
and his response was something along the lines of, "it's pretty good,
but I really don't like the column order." To make Jimmy happy, I
implemented the @OUTPUT_COLUMN_LIST option. To use this option, simply
pass in whatever columns you would like to see, in whatever order you
would like to see them, and the script will do the rest. Note that the
output will be the intersection of whatever options are enabled and
whatever columns are found in the list.&lt;/p&gt;&lt;p&gt;Here's an example I've been using in my own work recently:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;EXEC sp_WhoIsActive &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @OUTPUT_COLUMN_LIST = &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; '[login_name],[dd hh:mm:ss.mss],[sql_text],[reads],[writes],&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; [context_switches],[physical_io],[wait_info],[blocking_session_id],&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; [tempdb_writes],[tran_log_writes],[query_plan],[session_id]';&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Another feature I added that makes things a bit more dynamic and customizable is the &lt;b&gt;ability to sort the output&lt;/b&gt;
based on whatever column and direction you would like. Interested in
seeing the requests that are currently blocked? No need to scroll, just
ask for them to sort high:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;EXEC sp_WhoIsActive &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @SORT_COLUMN = '[blocking_session_id]',&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @SORT_COLUMN_DIRECTION = 'DESC';&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;While
viewing the results on the screen in SSMS is great, sometimes I like to
capture the results to a table for later analysis. So I added a few
features in this most recent version to support &lt;b&gt;automated collection&lt;/b&gt;. &lt;/p&gt;&lt;p&gt;To
begin with, I realized that the default, nicely-formatted output of the
script, while great for on-screen viewing, isn't good if you want to do
your own analysis later. So I added a new option, @FORMAT_OUTPUT, that
lets you &lt;b&gt;control whether the output is or is not formatted&lt;/b&gt;. The default value for the parameter is 1, keeping with the previous behavior.&lt;/p&gt;&lt;p&gt;I
also figured that if you want to do some later analysis it might be
nice to know what time period you're working with. So I added a column
called collection_time, which outputs a datetime instance representing
the &lt;b&gt;time that the script finished running&lt;/b&gt;.&lt;/p&gt;&lt;p&gt;Taking things
one step further, I decided that with all of the dynamic column options
it would be a pain to put together a table matching the output schema
if you start playing with different settings. So I made things easy; no
need to figure out what the output looks like; &lt;b&gt;the script will write a CREATE TABLE statement for you&lt;/b&gt;. Simply enable the @RETURN_SCHEMA option and collect the output value from the @SCHEMA parameter.&lt;/p&gt;&lt;p&gt;Finally,
due to nested INSERT/EXEC limitations, it's impossible to insert the
result into a table when calling the stored procedure. No worries, the
script will &lt;b&gt;insert its output into a table&lt;/b&gt; for you. Just tell it where to send the data, via the @DESTINATION_TABLE option.&lt;/p&gt;&lt;p&gt;Here's
an example of asking for the unformatted output schema, creating a
destination table based on the current day, and collecting data 10
times, waiting 15 seconds between each collection:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;DECLARE @destination_table VARCHAR(4000);&lt;br&gt;SET @destination_table = 'WhoIsActive_' + CONVERT(VARCHAR, GETDATE(), 112);&lt;br&gt;&lt;br&gt;DECLARE @schema VARCHAR(4000);&lt;br&gt;EXEC sp_WhoIsActive&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @FORMAT_OUTPUT = 0,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @RETURN_SCHEMA = 1,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @SCHEMA = @schema OUTPUT;&lt;br&gt;&lt;br&gt;SET @schema = &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; REPLACE&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; @schema, &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; '&amp;lt;table_name&amp;gt;', &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; @destination_table&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; );&lt;br&gt;&lt;br&gt;EXEC(@schema);&lt;br&gt;&lt;br&gt;DECLARE @i INT;&lt;br&gt;SET @i = 0;&lt;br&gt;&lt;br&gt;WHILE @i &amp;lt; 10&lt;br&gt;BEGIN;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; EXEC sp_WhoIsActive&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; @FORMAT_OUTPUT = 0,&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; @DESTINATION_TABLE = @destination_table;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SET @i = @i + 1;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WAITFOR DELAY '00:00:15'&lt;br&gt;END;&lt;br&gt;GO&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;One of the key reasons I created the &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2007/12/31/a-gift-of-script-for-2008-who-s-active-what-are-they-doing-and-who-is-blocked.aspx"&gt;original version&lt;/a&gt; of Who is Active? was to help &lt;b&gt;identify blocked and blocking SPIDs&lt;/b&gt;. And I thought it worked pretty well for that purpose until recently, when I discovered that &lt;a href="http://sqlblog.com/blogs/aaron_bertrand/archive/2009/03/21/six-reasons-you-should-be-nervous-about-parallelism.aspx"&gt;sys.dm_exec_requests fails to properly identify blocking when queries go parallel&lt;/a&gt;. Oops. Fixed in the new version; it now uses the waiting tasks DMV for this purpose, instead of the requests DMV.&lt;/p&gt;&lt;p&gt;As
part of this process I discovered that the joins to the tasks DMVs were
slightly flawed in v7.30, so I fixed them up. And I was able to play
some games to improve performance--enough that I decided to eliminate
the @TASK_INFO option, making this the default behavior. This means
that you'll always get &lt;b&gt;correct blocker identification&lt;/b&gt; from Who
is Active? v.8.40, along with a few bonus task-based metrics including
physical I/O stats and the number of context switches.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Interested in information about transactions? So are most DBAs, which is why I &lt;b&gt;promoted the transaction start time&lt;/b&gt;, which was previously embedded in the tran_log_writes column, &lt;b&gt;to a top-level column&lt;/b&gt;
of its own. This will still populate only with transactions that have
actually done a write, but from what my testers tell me this is okay
behavior. Let me know if you disagree. While I was in there I played
even more performance games, and greatly improved the speed of the
query when the @GET_TRANSACTION_INFO option is enabled.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;A few smaller fixes are also worth mentioning here. First of all, I tested the script against a &lt;b&gt;case-sensitive instance&lt;/b&gt;, and fixed a few issues there. So it should work for you no matter what collation you're using. Second, thanks to &lt;a href="http://sqlblog.com/blogs/adam_machanic/archive/2009/03/15/the-grouped-string-concatenation-challenge-is-closed.aspx#comments"&gt;a discussion I had with Roman Nowak&lt;/a&gt;, I was able to finally &lt;b&gt;solve the entitization problem&lt;/b&gt; that plagued the "clickable" query output produced by the script. Third, I put on my security hat and added some code to &lt;b&gt;verify input arguments&lt;/b&gt;, as well as did a review of all of the dynamic SQL used by the script to make sure that &lt;b&gt;it is not injectable&lt;/b&gt;.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Thank
you to everyone who sent me feedback and/or feature requests! If you
have an idea for th script, please make sure to send it my way. I have
quite a bit of momentum at the moment and want to keep going and see
just how far I can take this thing. &lt;b&gt;I can only do this with your help&lt;/b&gt;.&lt;/p&gt;&lt;p&gt;Enjoy! &lt;/p&gt;&lt;p&gt;&lt;a href="http://sqlblog.com/blogs/adam_machanic/attachment/13006.ashx"&gt;&lt;b&gt;Click here to download Who is Active? v8.40&lt;/b&gt;&lt;/a&gt;&lt;br&gt;&lt;/p&gt;
&lt;BR&gt;&lt;div class = "shareblock"&gt;&lt;span class = "shareblockTitle"&gt;Share this post:&lt;/span&gt;&lt;span class = "shareblockLink"&gt; &lt;a href = "mailto:?subject=Who is Active? v8.40 - Now With Delta Power!&amp;amp;body=Seen on SQLblog.com: %0A%0A%09Who is Active? v8.40 - Now With Delta Power!%0A%0Ahttp://sqlblog.com/blogs/adam_machanic/archive/2009/03/30/who-is-active-v8-40-now-with-delta-power.aspx" target="_blank" title = "Email Who is Active? v8.40 - Now With Delta Power!"&gt;email it!&lt;/a&gt; |  &lt;a href = "http://del.icio.us/post?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/03/30/who-is-active-v8-40-now-with-delta-power.aspx&amp;amp;title=Who+is+Active%3f+v8.40+-+Now+With+Delta+Power!" target="_blank" title = "Submit Who is Active? v8.40 - Now With Delta Power! to del.icio.us"&gt;bookmark it!&lt;/a&gt; |  &lt;a href = "http://www.digg.com/submit?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/03/30/who-is-active-v8-40-now-with-delta-power.aspx&amp;amp;phase=2" target="_blank" title = "Submit Who is Active? v8.40 - Now With Delta Power! to digg.com"&gt;digg it!&lt;/a&gt; |  &lt;a href = "http://reddit.com/submit?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/03/30/who-is-active-v8-40-now-with-delta-power.aspx&amp;amp;title=Who+is+Active%3f+v8.40+-+Now+With+Delta+Power!" target="_blank" title = "Submit Who is Active? v8.40 - Now With Delta Power! to reddit.com"&gt;reddit!&lt;/a&gt; |  &lt;a href = "http://www.dotnetkicks.com/submit/?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/03/30/who-is-active-v8-40-now-with-delta-power.aspx&amp;amp;title=Who+is+Active%3f+v8.40+-+Now+With+Delta+Power!" target="_blank" title = "Submit Who is Active? v8.40 - Now With Delta Power! to DotNetKicks"&gt;kick it!&lt;/a&gt; |  &lt;a href = "https://favorites.live.com/quickadd.aspx?marklet=1&amp;amp;mkt=en-us&amp;amp;url=http://sqlblog.com/blogs/adam_machanic/archive/2009/03/30/who-is-active-v8-40-now-with-delta-power.aspx&amp;amp;title=Who+is+Active%3f+v8.40+-+Now+With+Delta+Power!&amp;amp;;top=1" target="_blank" title = "Add Who is Active? v8.40 - Now With Delta Power! to Live Bookmarks"&gt;live it!&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;img src="http://info.sqlblog.com/a.aspx?ZoneID=0&amp;BannerID=12&amp;AdvertiserID=1&amp;CampaignID=12&amp;Task=Get&amp;Mode=TEXT&amp;SiteID=1&amp;RandomNumber=463323" width="1" height="1" border="0"&gt;&lt;img src="http://sqlblog.com/aggbug.aspx?PostID=13006" width="1" height="1"&gt;</description><enclosure url="http://sqlblog.com/blogs/adam_machanic/attachment/13006.ashx" length="14867" type="application/zip" /><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/Scripts/default.aspx">Scripts</category><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/DMVs/default.aspx">DMVs</category><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/who+is+active/default.aspx">who is active</category><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/monitoring/default.aspx">monitoring</category></item><item><title>About the SQLblog Roller Outage</title><link>http://sqlblog.com/blogs/adam_machanic/archive/2009/03/21/about-the-sqlblog-roller-outage.aspx</link><pubDate>Sat, 21 Mar 2009 19:24:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:12833</guid><dc:creator>Adam Machanic</dc:creator><slash:comments>3</slash:comments><comments>http://sqlblog.com/blogs/adam_machanic/comments/12833.aspx</comments><wfw:commentRss>http://sqlblog.com/blogs/adam_machanic/commentrss.aspx?PostID=12833</wfw:commentRss><description>&lt;p&gt;Over the past few days you might have noticed that the SQLblog &lt;a href="http://sqlblog.com/roller/roller.aspx"&gt;external feeds roller&lt;/a&gt; had mysteriously vanished.&amp;nbsp; We had some technical difficulties on Tuesday, things appeared to have fixed themselves by Wednesday morning, and then the problems returned Wednesday evening.&amp;nbsp; So I decided to disable the feature.&amp;nbsp; Honestly, I didn't think anyone would even notice, but I received some e-mails from some concerned parties; apparently there are people out there who actually use the roller.&lt;/p&gt;&lt;p&gt;The bad news is that we have no idea why this issue cropped up, but the good news is that I've been watching it now for three days and it seems fine. I've just turned it back on, and as part of the process of cleaning up the mess I even added a few new blogs to the list. As always, I'm looking for more great blogs to add, so if you have any ideas leave a comment here.&amp;nbsp; Enjoy, and please let me know if you see any further issues.&lt;br&gt;&lt;/p&gt;
&lt;BR&gt;&lt;div class = "shareblock"&gt;&lt;span class = "shareblockTitle"&gt;Share this post:&lt;/span&gt;&lt;span class = "shareblockLink"&gt; &lt;a href = "mailto:?subject=About the SQLblog Roller Outage&amp;amp;body=Seen on SQLblog.com: %0A%0A%09About the SQLblog Roller Outage%0A%0Ahttp://sqlblog.com/blogs/adam_machanic/archive/2009/03/21/about-the-sqlblog-roller-outage.aspx" target="_blank" title = "Email About the SQLblog Roller Outage"&gt;email it!&lt;/a&gt; |  &lt;a href = "http://del.icio.us/post?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/03/21/about-the-sqlblog-roller-outage.aspx&amp;amp;title=About+the+SQLblog+Roller+Outage" target="_blank" title = "Submit About the SQLblog Roller Outage to del.icio.us"&gt;bookmark it!&lt;/a&gt; |  &lt;a href = "http://www.digg.com/submit?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/03/21/about-the-sqlblog-roller-outage.aspx&amp;amp;phase=2" target="_blank" title = "Submit About the SQLblog Roller Outage to digg.com"&gt;digg it!&lt;/a&gt; |  &lt;a href = "http://reddit.com/submit?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/03/21/about-the-sqlblog-roller-outage.aspx&amp;amp;title=About+the+SQLblog+Roller+Outage" target="_blank" title = "Submit About the SQLblog Roller Outage to reddit.com"&gt;reddit!&lt;/a&gt; |  &lt;a href = "http://www.dotnetkicks.com/submit/?url=http://sqlblog.com/blogs/adam_machanic/archive/2009/03/21/about-the-sqlblog-roller-outage.aspx&amp;amp;title=About+the+SQLblog+Roller+Outage" target="_blank" title = "Submit About the SQLblog Roller Outage to DotNetKicks"&gt;kick it!&lt;/a&gt; |  &lt;a href = "https://favorites.live.com/quickadd.aspx?marklet=1&amp;amp;mkt=en-us&amp;amp;url=http://sqlblog.com/blogs/adam_machanic/archive/2009/03/21/about-the-sqlblog-roller-outage.aspx&amp;amp;title=About+the+SQLblog+Roller+Outage&amp;amp;;top=1" target="_blank" title = "Add About the SQLblog Roller Outage to Live Bookmarks"&gt;live it!&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;img src="http://info.sqlblog.com/a.aspx?ZoneID=0&amp;BannerID=12&amp;AdvertiserID=1&amp;CampaignID=12&amp;Task=Get&amp;Mode=TEXT&amp;SiteID=1&amp;RandomNumber=463323" width="1" height="1" border="0"&gt;&lt;img src="http://sqlblog.com/aggbug.aspx?PostID=12833" width="1" height="1"&gt;</description><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/SQLblog/default.aspx">SQLblog</category><category domain="http://sqlblog.com/blogs/adam_machanic/archive/tags/roller/default.aspx">roller</category></item></channel></rss>