<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://rentacoder.com/CS/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>Real Life Microsoft IT : Systems</title><link>http://rentacoder.com/CS/blogs/real_life_it/archive/category/1002.aspx</link><description /><dc:language>en-US</dc:language><generator>CommunityServer 2.0 (Build: 60217.2664)</generator><item><title>SQL Server 2005: The new &amp;quot;missing indexes&amp;quot; feature</title><link>http://rentacoder.com/CS/blogs/real_life_it/archive/2006/05/11/dm_db_missing_index_group_stats_SQL_Server_2005_The_new_missing_indexes_feature.aspx</link><pubDate>Thu, 11 May 2006 20:33:00 GMT</pubDate><guid isPermaLink="false">2b679553-572d-4457-89da-485055e17287:504</guid><dc:creator>admin</dc:creator><slash:comments>0</slash:comments><comments>http://rentacoder.com/CS/blogs/real_life_it/comments/504.aspx</comments><wfw:commentRss>http://rentacoder.com/CS/blogs/real_life_it/commentrss.aspx?PostID=504</wfw:commentRss><description>&lt;FONT size=2&gt;
&lt;P&gt;There is an interesting and useful&amp;nbsp;new feature in SQL 2005 where it takes all queries that execute and don't find an optimal index...and &lt;STRONG&gt;records&lt;/STRONG&gt; the information.&amp;nbsp; You can use this information to generate indexes and speed up your performance.&amp;nbsp; These are only held as long as your SQL Server is running...rebooting it will flush out any information stored.&lt;/P&gt;
&lt;P&gt;You get the information from a built in view documented in MSDN: sys.dm_db_missing_index_details&lt;BR&gt;&lt;A href="http://msdn2.microsoft.com/en-us/library/ms345405.aspx"&gt;http://msdn2.microsoft.com/en-us/library/ms345405.aspx&lt;/A&gt;&lt;BR&gt;&lt;BR&gt;However,&amp;nbsp;sys.dm_db_missing_index_details only take you half of the way home.&amp;nbsp; It lists the&amp;nbsp;pieces of the index to be created, but still requires you to construct the CREATE NONCLUSTERED INDEX SQL yourself.&amp;nbsp; This requires you to learn how to do it (from the above link)...which means understanding the internals of how it works.&amp;nbsp;&amp;nbsp; (According to this 2nd link, the SQL team initially implemented the "whole enchalida" and then later removed it: &lt;A href="http://solidqualitylearning.com/blogs/mike/archive/2005/09/26/1455.aspx"&gt;http://solidqualitylearning.com/blogs/mike/archive/2005/09/26/1455.aspx&lt;/A&gt;&amp;nbsp;)&lt;BR&gt;&lt;BR&gt;The link above&amp;nbsp;argues that this is a good thing, becuase it says that these are&amp;nbsp;just suggestions rather than guarantees (and you still need to verify that you want to truly run each one).&amp;nbsp; If this is true...I would argue back that forcing someone to piece together everything to create the query doesn't reinforce the fact that it's a suggestion.&amp;nbsp; It just aggravates the DBA.&amp;nbsp; The proper way to do this would be to just &lt;STRONG&gt;document&lt;/STRONG&gt; that these are just suggestions in the reference on this stored procedure...not make it harder on the DBA who might have to implement it.&lt;BR&gt;&lt;BR&gt;Anyway...fortunately for you (or unfortunately...depending on your point of view), I've&amp;nbsp;created the following that will create the SQL for you.&amp;nbsp; :) What it does is takes the top 10 queries that the view says would improve most from new indices and creates the SQL statement for them.&amp;nbsp; You can adjust the # returned&amp;nbsp;by changing: SELECT TOP (10) group_handle.&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;SELECT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'CREATE NONCLUSTERED INDEX &amp;lt;NewNameHere&amp;gt; ON ' + sys.objects.name + ' ( ' + mid.equality_columns + CASE WHEN mid.inequality_columns IS NULL&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; THEN '' ELSE CASE WHEN mid.equality_columns IS NULL &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; THEN '' ELSE ',' END + mid.inequality_columns END + ' ) ' + CASE WHEN mid.included_columns IS NULL &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; THEN '' ELSE 'INCLUDE (' + mid.included_columns + ')' END + ';' AS CreateIndexStatement, mid.equality_columns, mid.inequality_columns, &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; mid.included_columns&lt;BR&gt;FROM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sys.dm_db_missing_index_group_stats AS migs INNER JOIN&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; sys.dm_db_missing_index_groups AS mig ON migs.group_handle = mig.index_group_handle INNER JOIN&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; sys.dm_db_missing_index_details AS mid ON mig.index_handle = mid.index_handle INNER JOIN&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; sys.objects WITH (nolock) ON mid.object_id = sys.objects.object_id&lt;BR&gt;WHERE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (migs.group_handle IN&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; (SELECT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; TOP (10) group_handle&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; FROM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sys.dm_db_missing_index_group_stats WITH (nolock)&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; ORDER BY (avg_total_user_cost * avg_user_impact) * (user_seeks + user_scans) DESC))&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;Sample Output:&lt;BR&gt;CREATE NONCLUSTERED INDEX &amp;lt;NewNameHere&amp;gt; ON MYtable ( [PId], [PersonId], [Hidden] ) INCLUDE ([Id], [BRId], [Amount], [Comment], [OtherDate], [ParentBId]);&lt;BR&gt;&lt;BR&gt;Caveats:&lt;/P&gt;
&lt;P&gt;1) Before adding each one...review it and make sure you really want to add it to your database.&amp;nbsp; Per &lt;BR&gt;&lt;A href="http://solidqualitylearning.com/blogs/mike/archive/2005/09/26/1455.aspx"&gt;http://solidqualitylearning.com/blogs/mike/archive/2005/09/26/1455.aspx&lt;/A&gt;&lt;BR&gt;"These are &lt;STRONG&gt;suggestions&lt;/STRONG&gt;, not absolutes.&amp;nbsp; It still requires a DBA to take a look at the index and decide whether it should be created."&lt;BR&gt;&lt;BR&gt;2) Use this at your own risk.&amp;nbsp; I experienced a few times where I followed the MSDN article's steps exactly (which is what this view is based on) and it wouldn't create the index properly.&amp;nbsp; Example: sometimes the INCLUDE field returned by the system view has text fields in it.&amp;nbsp; But actually using it in the INCLUDE results in this error:&lt;BR&gt;&lt;BR&gt;&lt;FONT size=1&gt;&lt;EM&gt;Column 'TextField' in table 'myTable' is of a type that is invalid for use as included column in an index.&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;So test the SQL first on your dev server and make sure it's right.&lt;BR&gt;&lt;BR&gt;3) The generated SQL&amp;nbsp;doesn't do one thing recommended by MSDN.&amp;nbsp;&amp;nbsp;It says "To determine an effective order for the equality columns, order them based on their selectivity; that is, list the most selective columns first."&amp;nbsp; Doing this automatically would take more time than I had to devote to this.&amp;nbsp; So check the order of the SQL produced and if the index fields aren't in the order you'd like, you can change them around.&amp;nbsp; And if anyone wishes to create something that handles this too...then please post it here.&amp;nbsp; &lt;BR&gt;&lt;BR&gt;Ian Ippolito&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;img src="http://rentacoder.com/CS/aggbug.aspx?PostID=504" width="1" height="1"&gt;</description><category domain="http://rentacoder.com/CS/blogs/real_life_it/archive/category/1002.aspx">Systems</category></item><item><title>How SQL Server 2005 &amp;quot;Forced Parameterization&amp;quot; cut ad-hoc query CPU usage by 85%</title><link>http://rentacoder.com/CS/blogs/real_life_it/archive/2006/04/30/487.aspx</link><pubDate>Mon, 01 May 2006 00:11:00 GMT</pubDate><guid isPermaLink="false">2b679553-572d-4457-89da-485055e17287:487</guid><dc:creator>admin</dc:creator><slash:comments>1</slash:comments><comments>http://rentacoder.com/CS/blogs/real_life_it/comments/487.aspx</comments><wfw:commentRss>http://rentacoder.com/CS/blogs/real_life_it/commentrss.aspx?PostID=487</wfw:commentRss><description>&lt;P&gt;&lt;STRONG&gt;Is it my imagination or is&amp;nbsp;SQL 2005 running slower?&lt;/STRONG&gt;&lt;BR&gt;&lt;BR&gt;My first impresson&amp;nbsp;with SQL Server 2005 came after installing it on a test server.&amp;nbsp; The test server is a dual processor machine...which&amp;nbsp;was a pretty high powered box back in it's hey-day, but these days it's a commodity server.&amp;nbsp; It runs both SQL Server and IIS,so it is more sensitive to&amp;nbsp;load problems&amp;nbsp;than the production server.&amp;nbsp; This make it a good "canary in a coal-mine", because it detects and helps flush out performance problems early in the process.&lt;/P&gt;
&lt;P&gt;The first thing I noticed with 2005, was that every time I rebooted the machine, the first time I ran a particular web page (which ran queries to SQL ),&amp;nbsp;SQL Server 2005&amp;nbsp;would take a really long time to return the results. In 2000, it would run in about&amp;nbsp;7 seconds, but in 2005 it would timeout the web page (meaning it took at least 10 seconds). But after that first call it would be fine..and would&amp;nbsp;actually run faster than 7 seconds.&amp;nbsp;&amp;nbsp; This weird problem would only occur after every reboot...and would then disappear.&lt;BR&gt;&lt;BR&gt;Since I had hundreds of other tasks that needed to be done for the upgrade, and it only happened on bootup, I simply increased the timeout on the page to&amp;nbsp;15 seconds, and pressed on to other matters.&amp;nbsp; But it stayed in the back of my mind.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;SQL Server 2005: Faster to Execute but Slower to Compile?&lt;/STRONG&gt;&lt;BR&gt;&lt;BR&gt;All versions of SQL Server first compile a query and then execute it.&amp;nbsp; I have seen many times where SQL Server 2005&amp;nbsp;executes queries faster than 2000...but I have also seen many times where it took longer to compile them in the first place.&amp;nbsp; Most likely the two are related...it takes more time to create a better query plan. &lt;BR&gt;&lt;BR&gt;This isn't necessarily a bad thing.&amp;nbsp; In fact, if&amp;nbsp;100% of your workload is stored procedures, it is a great improvement.&amp;nbsp; That is because&amp;nbsp;stored procs&amp;nbsp;are precompiled, so they are only compiled once&amp;nbsp;and executed many times.&amp;nbsp;So if this is your situation, then you will save many multiples of time more than you are giving up.&lt;BR&gt;&lt;BR&gt;BUT...if on the other hand if your workload has a large percentage of ad hoc queries (for example: SQL called from a programming language like ASP.NET), then the situation will be reversed.&amp;nbsp; That is becuase ad hoc queries&amp;nbsp;have to be&amp;nbsp;compiled each and every time they need to be run.&amp;nbsp; And if this is your case, then they will run slower in 2005 than in 2000.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Workarounds&lt;/STRONG&gt;&lt;BR&gt;&lt;BR&gt;In an ideal world this would not be a problem, becuase everything would be written in stored procedures.&amp;nbsp; However, this ideal case doesn't always exist.&amp;nbsp; Some apps use 3rd party middle tier components which preclude the abilty to implement stored procs.&amp;nbsp; Others&amp;nbsp;require the ability to run on multiple vendor databases...meaning they&amp;nbsp;can only use&amp;nbsp;vendor-neutral SQL.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;The more typical application&amp;nbsp;is homegrown and designed only for SQL Server, so it doesn't have any of the above problems.&amp;nbsp; These apps typically&amp;nbsp;use stored procs when they can, but but&amp;nbsp;use&amp;nbsp;an adhoc query&amp;nbsp;when they can't.&amp;nbsp; For example,&amp;nbsp;a search screen with many paramaters creates very complex SQL that&amp;nbsp;morphs dramatically from query to query.&amp;nbsp; If you choose one set of options, you might get a simple query, and if you choose others, you may have to INNER or OUTER JOIN to 10-11 additional tables, new fields, WHERE, HAVING, GROUP BY clauses, etc.&amp;nbsp; This easy to code in a declarative language like .NET.&amp;nbsp; But this sort of structure&amp;nbsp;is an exponentially growing nightmare in a true TSQL stored procedure.&amp;nbsp; .NET stored procs are a leg up on TSQL and can make non-set based operations easier to do.&amp;nbsp;&amp;nbsp;But they are little slower than TSQL.&amp;nbsp;&amp;nbsp;More imporantly, all stored procedures (including .NET, TSQL and even dynamic TSQL), cause a fundamental programming problem. Coding them requires maintaining an interface in two places...in the stored proc and in the code.&amp;nbsp; Every change requires two changes rather than one...and every time new functionality is added, this usually requires an interface change.&amp;nbsp; This translates into double the development time, double the chances for bugs and double the work.&lt;BR&gt;&lt;BR&gt;&lt;STRONG&gt;Is there another way?&lt;/STRONG&gt;&lt;BR&gt;&lt;BR&gt;But what if there were a way to&amp;nbsp;get:&lt;BR&gt;1) The performance of a TSQL stored proc&amp;nbsp;&lt;BR&gt;2)&amp;nbsp;The power and flexibility of a declarative language&lt;BR&gt;3) That only requires one interface?&lt;/P&gt;
&lt;P&gt;Before you say "Keep dreaming!"...I'd recommend that.you&amp;nbsp;read&amp;nbsp;the book "Good to Great".&amp;nbsp; In that book&amp;nbsp;the author talks about "good" companies being ruled by the "tyranny of the OR" and "great" companies&amp;nbsp;believing&amp;nbsp;in the "genius of the and".&amp;nbsp; For example, a "good" company&amp;nbsp;would believe they could either offer the cheapest price, or good quality but not both.&amp;nbsp; A "great" company would find a way to do both.&lt;BR&gt;&lt;BR&gt;Is it possible to&amp;nbsp;harness the "genuis of the AND" in our database situation?&amp;nbsp; The developers of SQL Server 2005 dared to ask that question.&amp;nbsp;&amp;nbsp;And the result of that is a wonderous creation.&amp;nbsp;&amp;nbsp;The name&amp;nbsp;doesn't do it enough&amp;nbsp;justice and has probably caused it to be one of the least heralded and unheard of features in SQL Server 2005.&amp;nbsp; (Do a search on Google and you'll find perhaps 6 mentions on the entire web...none in Microsoft's marketing.)&amp;nbsp; This little known&amp;nbsp;feature is&amp;nbsp;called "forced parameterization".&amp;nbsp; &lt;BR&gt;&lt;STRONG&gt;&lt;BR&gt;That sounds familiar&lt;/STRONG&gt;&lt;BR&gt;&lt;BR&gt;You may have heard of the term "parmaterization" before. Simple parameterization was SQL 2000's first attempt at finding the "genius of the AND".&amp;nbsp;&amp;nbsp; Genius solutions don't come easily... and this first attempt was a nice step in the right direction but ultimately fell short.&amp;nbsp; &lt;BR&gt;&lt;BR&gt;Basically, SQL would analyze your non stored proc queries and figure out for itself if it could create a query plan on the fly with it.&amp;nbsp; It did this by subbing out some of the values you entered with paramaters that could be reused by similar queries.&amp;nbsp; The only problem was that it was very simple and didn't handle many real life situations (such as an IN clause for excample).&amp;nbsp; Worse, changing the query just a little bit could often "fool" it into not recognizing it as being the same as the original, and it wouldn't "kick in".&amp;nbsp; So while&amp;nbsp;simple&amp;nbsp;parmaterization&amp;nbsp;helped a little, it wasn't enough of&amp;nbsp;a&amp;nbsp;solution to solve the problem. &lt;BR&gt;&lt;BR&gt;Microsoft put the intervening 5 years between 2005 and 2005 to good use and basically revamped&amp;nbsp;this&amp;nbsp;code&amp;nbsp;entirely and pumped it up on steriods.&amp;nbsp;&amp;nbsp;Possibly the&amp;nbsp;incredible increase in CPU processing power in those 5 years led them to&amp;nbsp;believe that their customers would have the horse power to enable such a solution to run effectively.&amp;nbsp; They made it more robust, more dynamic and more powerful, and yet&amp;nbsp;kept it lightning quick.&amp;nbsp;&amp;nbsp;They enabled it to do&amp;nbsp;handle a&amp;nbsp;much larger&amp;nbsp;variety of queries.&amp;nbsp; And most importantly...if it wasn't able to figure out a certain part of the query, it didn't just "give up" (as simple paramaterization did/does)...it just skipped&amp;nbsp;that small portion&amp;nbsp;and paramaterized the rest.&amp;nbsp; &lt;BR&gt;&lt;BR&gt;They called this feature "forced paramaterization".&amp;nbsp;&lt;BR&gt;&lt;BR&gt;&lt;STRONG&gt;What does this mean in real life?&amp;nbsp;&lt;/STRONG&gt;&lt;BR&gt;&lt;BR&gt;So what does this mean to you?&amp;nbsp; &amp;nbsp;I ran this test during an offpeak time period, but during which a large # of ad hoc queries are typically run.&amp;nbsp; With simple paramaterization (which is on by default), the result was a 25% average CPU utilization:&lt;/P&gt;
&lt;P&gt;&lt;A href="https://www.rentacoder.com/CS/photos/general_photo_gallery/picture485.aspx" target=_blank&gt;&lt;IMG src="https://www.rentacoder.com/CS/photos/general_photo_gallery/images/485/original.aspx" border=0&gt;&lt;/A&gt;&lt;BR&gt;&lt;BR&gt;Not bad.&amp;nbsp; So then I&amp;nbsp;turned on forced parameterization.&amp;nbsp; It's done at the database level under "properties" and "options".&amp;nbsp; This was the result:&lt;BR&gt;&lt;BR&gt;&lt;A href="https://www.rentacoder.com/CS/photos/general_photo_gallery/picture486.aspx" target=_blank&gt;&lt;/A&gt;&lt;A href="https://www.rentacoder.com/CS/photos/general_photo_gallery/picture486.aspx" target=_blank&gt;&lt;IMG src="https://www.rentacoder.com/CS/photos/general_photo_gallery/images/486/original.aspx" border=0&gt;&lt;/A&gt;&lt;BR&gt;&lt;BR&gt;At first I thought something had to be wrong.&amp;nbsp;The processor usage dropped to&amp;nbsp;1/5th of what it had been before...just 5%!&amp;nbsp;&amp;nbsp;&amp;nbsp;Had everyone stopped using the database all of a sudden?&amp;nbsp;&amp;nbsp;I paniced for a minute and then settled down&amp;nbsp;once I&amp;nbsp;confirmed that there was no site-wide emergency and things were actually running normally.&amp;nbsp; I&amp;nbsp;watched it very closely&amp;nbsp;for 10 minutes, and "force parameterization" took on query after query like&amp;nbsp;a champ and didn't even break a sweat.&amp;nbsp; The # of cached query plans rose as the CPU kept low.&amp;nbsp; Clearly the compiling of the ad hoc queries was a bottleneck before-hand and "forced parameterization" wiped out that bottleneck like a truck running over an ice cream cone!&lt;BR&gt;&lt;BR&gt;And the best thing about it is that it tends to get better with time.&amp;nbsp; As more queries run, more get cached, and your server runs faster and faster.&amp;nbsp; By removing that compiling bottleneck your ad-hoc queries fly!&lt;BR&gt;&lt;BR&gt;&lt;STRONG&gt;Is there a Downside?&lt;BR&gt;&lt;/STRONG&gt;&lt;BR&gt;Genius doesn't come easy.&amp;nbsp; There are some cases where even forced paramaterization doesn't work.&amp;nbsp;&amp;nbsp;It may have a tendency to make your queries not use indexed views (if you are using them).&amp;nbsp; And now that your ad hoc queries have the pre-compilation powers of stored procs, they have&amp;nbsp;the downsides&amp;nbsp;of that power as well.&amp;nbsp; Particularly sometimes a compiled plan for a typical situation doesn't work right for an outlier situation (or vice versa) and can effect performance.&amp;nbsp; But this is a rare situation and can be handled on a case by case basis if and when it happens.&amp;nbsp; You can read the help files on the feature for more information on the pros and cons of forced parameterization and decide for yourself when it might or might not be appropriate for you. &lt;BR&gt;&lt;BR&gt;But for us, it has been a godsend and we will continue to use it in production.&amp;nbsp; And I can't wait to see how this feature expands in the next release.&lt;BR&gt;&lt;BR&gt;Kudos to the SQL Server 2005 team on this little talked about but great feature.&lt;BR&gt;&lt;BR&gt;Links:&lt;BR&gt;Here is a good blog entry from a Microsoft SQL Server developer named &lt;U&gt;&lt;FONT color=#0000ff&gt;Cihangir Biyikoglu&lt;/FONT&gt;&lt;/U&gt;&amp;nbsp;on the feature:&lt;BR&gt;&lt;A href="http://blogs.msdn.com/cbiyikoglu/archive/2005/11/03/488920.aspx"&gt;http://blogs.msdn.com/cbiyikoglu/archive/2005/11/03/488920.aspx&lt;/A&gt;&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;Ian Ippolito&lt;/P&gt;&lt;img src="http://rentacoder.com/CS/aggbug.aspx?PostID=487" width="1" height="1"&gt;</description><category domain="http://rentacoder.com/CS/blogs/real_life_it/archive/category/1002.aspx">Systems</category></item><item><title>A &amp;quot;must use&amp;quot; SQL Server 2005 Feature-ROW_NUMBER()</title><link>http://rentacoder.com/CS/blogs/real_life_it/archive/2006/04/29/481.aspx</link><pubDate>Sat, 29 Apr 2006 15:30:00 GMT</pubDate><guid isPermaLink="false">2b679553-572d-4457-89da-485055e17287:481</guid><dc:creator>admin</dc:creator><slash:comments>1</slash:comments><comments>http://rentacoder.com/CS/blogs/real_life_it/comments/481.aspx</comments><wfw:commentRss>http://rentacoder.com/CS/blogs/real_life_it/commentrss.aspx?PostID=481</wfw:commentRss><description>&lt;FONT size=2&gt;
&lt;P&gt;If you run your SQL Server as the back end for a website, then paging is one of the most common things that you do.&amp;nbsp; In SQL Server 2000, doing this paging was complicated and resource intensive.&amp;nbsp; But in 2005, there is a new feature called ROW_NUMBER than you can combine with BETWEEN that will give you orders of magnitude improvement. &lt;BR&gt;&lt;BR&gt;SQL Server Processor utlization before ROW_NUMBER (Last Saturday):&lt;/P&gt;
&lt;P&gt;&lt;A href="https://www.rentacoder.com/CS/photos/general_photo_gallery/picture482.aspx" target=_blank&gt;&lt;IMG src="https://www.rentacoder.com/CS/photos/general_photo_gallery/images/482/original.aspx" border=0&gt;&lt;/A&gt;&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;SQL Server Processor utlization after ROW_NUMBER (the cutover is plainly visible at around 1:30 AM this Saturday):&lt;BR&gt;&lt;A href="https://www.rentacoder.com/CS/photos/general_photo_gallery/picture483.aspx" target=_blank&gt;&lt;IMG src="https://www.rentacoder.com/CS/photos/general_photo_gallery/images/483/original.aspx" border=0&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;A href="https://www.rentacoder.com/CS/photos/general_photo_gallery/picture482.aspx" target=_blank&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;When pushed to production,&amp;nbsp;he CPU&amp;nbsp;INSTANTANEOUSLY dropped from an average of about 50% CPU toabout &amp;nbsp;25% CPU, and stayed there!&amp;nbsp; That's a&amp;nbsp;50% reduction in CPU just from one query change!&amp;nbsp; If you run a website with SQL Server, this should be one of the FIRST things you look at after you upgrade.&lt;/P&gt;
&lt;P&gt;Here are the best sources I found on how to implement it:&lt;BR&gt;&lt;BR&gt;1) &lt;A href="http://sqljunkies.com/WebLog/amachanic/archive/2004/11/03/4945.aspx"&gt;http://sqljunkies.com/WebLog/amachanic/archive/2004/11/03/4945.aspx&lt;/A&gt;&lt;BR&gt;&lt;BR&gt;Adam Mechanic ran some tests on the new ROW_NUMBER feature using paging and shows dramatic results.&amp;nbsp; The SQL 2000 style SQL returns a cost of 5,516.&amp;nbsp; The new 2005 style SQL returns a cost of 0.202!&lt;BR&gt;&lt;BR&gt;SQL 2000 style:&lt;BR&gt;&lt;BR&gt;&lt;EM&gt;SELECT x.SomewhatLargeString&lt;BR&gt;FROM (&lt;BR&gt;SELECT TOP 20010 A.SomewhatLargeString, COUNT(*) AS TheCount&lt;BR&gt;FROM #BigTableOfStrings A&lt;BR&gt;JOIN #BigTableOfStrings B ON B.SomewhatLargeString &amp;lt;= A.SomewhatLargeString&lt;BR&gt;GROUP BY A.SomewhatLargeString&lt;BR&gt;ORDER BY A.SomewhatLargeString ) x&lt;BR&gt;WHERE x.TheCount BETWEEN 20001 AND 20010&lt;BR&gt;&lt;/EM&gt;&lt;BR&gt;SQL 2005 Style:&lt;BR&gt;&lt;BR&gt;&lt;EM&gt;SELECT x.SomewhatLargeString,x.TheCount&lt;BR&gt;FROM (&lt;BR&gt;SELECT TOP 20010 A.SomewhatLargeString, ROW_NUMBER() OVER(ORDER BY A.SomewhatLargeString) AS TheCount&lt;BR&gt;FROM #BigTableOfStrings A&lt;BR&gt;ORDER BY A.SomewhatLargeString) x&lt;BR&gt;WHERE x.TheCount BETWEEN 20000 AND 20010&lt;BR&gt;&lt;/EM&gt;&lt;BR&gt;When you look at any new queries implementing ROW_NUMBER with BETWEEN, you may first wonder why there are 2 queries (the base query nested inside a top level query).&amp;nbsp; I did too.&amp;nbsp; I wondered, "Why not combine it into one query"?&amp;nbsp; The reason was clarified to me in a support ticket to Microsoft while trying to do this with a SELECT DISTINCT subquery.&amp;nbsp; By design, SQL Server&amp;nbsp;cannot referenced an aliased field using a WHERE clause (which is where the BETWEEN is located).&amp;nbsp; And you can't reference the "actual" field name for ROW_NUMBER(), becuase there&amp;nbsp;is no&amp;nbsp;actual field name.&amp;nbsp; So to work around it, the solution is to wrap the query in a top level query that pull at least the aliased field...and in that process, the field now becomes the "actual" field name at the top level and can be referenced by the WHERE/BETWEEN.&amp;nbsp; If that doesn't make sense...you don't need to understand it to use it...just copy the sytax above and USE IT.&lt;/P&gt;
&lt;P&gt;The other tip is to also&amp;nbsp;use the TOP setting in the inner select and set it to the highest # in your range of rows.&amp;nbsp; It will speed up the query and you don't need any rows past that anyway, so it's a "free boost".&lt;BR&gt;&lt;BR&gt;2) &lt;A href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnsql90/html/sql_05TSQLEnhance.asp"&gt;http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnsql90/html/sql_05TSQLEnhance.asp&lt;/A&gt;&lt;BR&gt;&lt;BR&gt;Microsoft's information&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;Ian Ippolito&lt;/P&gt;&lt;img src="http://rentacoder.com/CS/aggbug.aspx?PostID=481" width="1" height="1"&gt;</description><category domain="http://rentacoder.com/CS/blogs/real_life_it/archive/category/1002.aspx">Systems</category></item><item><title>SQL Server 2005 performance testing with hyperthreading and MAX DOP</title><link>http://rentacoder.com/CS/blogs/real_life_it/archive/2006/04/18/SQL_Server_2005_performance_testing_with_hyperthreading_and_MAX_DOP.aspx</link><pubDate>Wed, 19 Apr 2006 03:20:00 GMT</pubDate><guid isPermaLink="false">2b679553-572d-4457-89da-485055e17287:458</guid><dc:creator>admin</dc:creator><slash:comments>1</slash:comments><comments>http://rentacoder.com/CS/blogs/real_life_it/comments/458.aspx</comments><wfw:commentRss>http://rentacoder.com/CS/blogs/real_life_it/commentrss.aspx?PostID=458</wfw:commentRss><description>&lt;P&gt;There's been alot of negative publicity about hyperthreading (see "&lt;SPAN class=h1&gt;Hyperthreading hurts server performance, say developers" which is all over the net...including: &lt;/SPAN&gt;&lt;A href="http://news.zdnet.co.uk/0,39020330,39237341,00.htm"&gt;http://news.zdnet.co.uk/0,39020330,39237341,00.htm&lt;/A&gt;) &lt;BR&gt;&lt;BR&gt;We had been experiencing disapointing results upgrading from a 32 bit dual processor/single core machine to a 64-bit quad processors/dual core machine with hyperthreading...so I figured this was a good setting to experiment with.&amp;nbsp; &lt;BR&gt;&lt;BR&gt;The other setting&amp;nbsp;that gets alot of attention is the "Max Degree of Parallelism--Max DOP".&amp;nbsp; This setting tells SQL Server how many processors to use when running a multiple query.&amp;nbsp; If set to 0, it uses all available processors.&amp;nbsp; Otherwise you can limit it to a lower # using this paramater.&amp;nbsp; The advice on the internet&amp;nbsp;ranges from "leave it to 0" (which means use all processors), to "set it to the # of processors but don't count your hyperthreaded processors as 2" to "set it to 1". So this was also a good setting to experiment with.&amp;nbsp;&lt;BR&gt;&lt;BR&gt;&lt;STRONG&gt;Environment:&lt;BR&gt;&lt;/STRONG&gt;&lt;BR&gt;So I performed several tests using the &lt;A href="http://www.rentacoder.com/"&gt;http://www.RentACoder.com&lt;/A&gt; database to determine if it would help.&amp;nbsp; I picked a period of the night when the traffic was low (in case something got really messed up) but relatively constant and no odd batch jobs or mailing lists were running.&lt;BR&gt;Equipment: Quad processor (3.1 ghz) Dual Core 64-bit machine with 16GB memory.&lt;BR&gt;Software: SQL Server 2005 64 bit edition and Windows 2003 SP1.&lt;BR&gt;(note: some articles said that Windows 2003 SP1 was the most optimized system for hyperthreading).&lt;BR&gt;&lt;BR&gt;&lt;STRONG&gt;Raw Test results:&lt;BR&gt;&lt;/STRONG&gt;&lt;BR&gt;1)Baseline: Hyperthreading on...MAXDOP=0: At 9PM (a lull period) with hyperthreading enabled, the CPU usage ranged from 50-60%.&amp;nbsp; The MAXDOP=0 used 16 virtual processors (4 physical x 2 cores/processor x 2 hyperthreads/processor)&lt;BR&gt;2) Hyperthreading off...MAXDOP=0.&amp;nbsp; The CPU usage increased a small but noticable amount...and ranged from 60-70%.&amp;nbsp; The MAXDOP=0 used&amp;nbsp;8 virtual processors (4 physical x 2 cores/processor)&lt;BR&gt;3) Hyperthreading off...MAXDOP=4.&amp;nbsp; This test tested setting it to the # of physical processors (4). This was a CPU killer.&amp;nbsp; Usage spiked to 90-100%.&lt;BR&gt;&lt;BR&gt;&lt;STRONG&gt;Conclusion:&lt;/STRONG&gt;&lt;/P&gt;&lt;STRONG&gt;&lt;/STRONG&gt;
&lt;P&gt;In this case, hyperthreading really did produce a measureable boost in performance of 10%.&amp;nbsp;&amp;nbsp;Deactivating it permanently,&amp;nbsp;would have dropped performance&amp;nbsp;unnecessarily. &lt;BR&gt;&lt;BR&gt;Setting MAXDOP = to the # of physical processors really killed performance...the default MAXDOP setting=0 performed much better.&amp;nbsp; Note: I didn't try changing MAXDOP with hyperthreading enabled...perhaps that is a test for another time.&lt;BR&gt;&lt;BR&gt;&lt;STRONG&gt;Bottom Line:&lt;BR&gt;&lt;/STRONG&gt;&lt;BR&gt;Don't trust "experts" who tell you that hyperthreading doesn't work...test it for yourself.&amp;nbsp; You may get a boost as we do from it.&amp;nbsp; MAXDOP tuning did not produce an increase in performance and actually hurt performance.&amp;nbsp; So if you experiment do so during a lull period where you won't flood yourself with complaints if your CPU usage spikes.&lt;BR&gt;&lt;BR&gt;Ian Ippolito&lt;/P&gt;&lt;img src="http://rentacoder.com/CS/aggbug.aspx?PostID=458" width="1" height="1"&gt;</description><category domain="http://rentacoder.com/CS/blogs/real_life_it/archive/category/1002.aspx">Systems</category></item><item><title>Classic ASP: Not ready for prime-time?</title><link>http://rentacoder.com/CS/blogs/real_life_it/archive/2006/03/19/448.aspx</link><pubDate>Sun, 19 Mar 2006 15:56:00 GMT</pubDate><guid isPermaLink="false">2b679553-572d-4457-89da-485055e17287:448</guid><dc:creator>admin</dc:creator><slash:comments>4</slash:comments><comments>http://rentacoder.com/CS/blogs/real_life_it/comments/448.aspx</comments><wfw:commentRss>http://rentacoder.com/CS/blogs/real_life_it/commentrss.aspx?PostID=448</wfw:commentRss><description>&lt;P&gt;There is a&amp;nbsp;VERY bad problem with&amp;nbsp;Active Server Pages (ASP...or what is sometimes known as "classic ASP") which prevents it from being a viable system on which to build a "big IT" project.&amp;nbsp; For 2 years we've been fighting a problem in which the IIS (Internet Information Server) 6.0 web servers will run fine for a while.&amp;nbsp; But then after 18-20 hours,&amp;nbsp;every pages will stop running properly and instead display random errors (that change from refresh of the page to refresh).&amp;nbsp; The errors always say things like "Cannot find property or method" regarding classes that do exist, or "Cannot create object".&amp;nbsp; The exact propery or object changes from "refresh" to "resfresh"...even on the same page. Restarting will fix the problem for an hour or so...but then it reoccurs.&amp;nbsp; Only a hard reboot will fix it for another 18-20 hours.&amp;nbsp; And then the cycle repeats itself.&lt;/P&gt;
&lt;P&gt;We started a ticket over 2 years on this.&amp;nbsp; Today Microsoft acknowledged the problem&amp;nbsp;publicly with a KB article: &lt;A href="http://support.microsoft.com/?scid=kb;en-us;914156"&gt;http://support.microsoft.com/?scid=kb;en-us;914156&lt;/A&gt;&lt;BR&gt;&lt;BR&gt;Basically the problem is that ASP fragments the heap under certain conditions:&lt;BR&gt;1) When an app uses INCLUDE files &lt;BR&gt;2) When an app uses&amp;nbsp;significant memory&lt;BR&gt;And it&amp;nbsp;doesn't defragment&amp;nbsp;the memory&amp;nbsp;and as a result,&amp;nbsp;will ALWAYS&amp;nbsp;crash IIS in this way.&amp;nbsp; The new restart services of IIS 6.0 don't help, becuase only a hard reboot can truly get rid of the defragmentation.&amp;nbsp; &lt;BR&gt;&lt;BR&gt;Of course, two things that any&amp;nbsp;site that has any sophistication has lots of INCLUDE files and any site that has any traffic uses&amp;nbsp;lots of memory.&amp;nbsp;&amp;nbsp;If both of these apply to you, your ASP site is in trouble.&amp;nbsp; This is what's called a "bug" in my book.&amp;nbsp; I'm sure if ASP were&amp;nbsp;MSFT's current technology they would have to fix this.&amp;nbsp; But Microsoft has moved on to ASP.NET...so I suspect the incentive is pretty much nil.&lt;BR&gt;&lt;BR&gt;If you look at the KB article, Microsoft gives a "workaround" (which is the same workaround that they suggested to us).&amp;nbsp; The workaround is to rewrite your INCLUDE files as COM objects.&amp;nbsp; The article sites a&amp;nbsp;# of benefits like speed, etc..&lt;BR&gt;&lt;BR&gt;The KB was probably written by a systems engineer who knows alot about running systems, but has no idea how&amp;nbsp;computer software is developed, and&amp;nbsp;how impractical this workaround is in the real world.&amp;nbsp; In a previous position we went down the COM object&amp;nbsp;route.&amp;nbsp; We did it for other reasons...becuase it was the Microsoft "best practice" at the time.&amp;nbsp; It's obvious why it no longer is.&amp;nbsp; The problems we ran into were:&lt;BR&gt;&lt;BR&gt;1) Memory: COM objects have a known memory leak problem.&amp;nbsp; If two COM objects reference each other and you set them to Nothing, they don't clear themselves in memory as they should.&amp;nbsp; The problem is due to the internal way that COM objects work and was fixed&amp;nbsp;in .NET with a rearchitecture.&amp;nbsp; But that isn't an option for you if you use&amp;nbsp;COM objects.&amp;nbsp; This COM memory leak bug will cause your machine to eventually crash, EVERY TIME.&lt;BR&gt;&lt;BR&gt;2)&amp;nbsp;Slowness to initialize objects:&amp;nbsp; COM objects are not designed to be created and destroyed thousands of times like .NET objects.&amp;nbsp;&amp;nbsp;&amp;nbsp;Our object rich COM model running on the internet was VERY slow...some pages took 5-10 seconds to render.&amp;nbsp;&amp;nbsp;One way to work around this is to not use objects in COM, but instead use functions.&amp;nbsp; But of course, this "solution" causes almost as many problems.&amp;nbsp; A non-object oriented framework is exponentially more difficult to debug and maintain which makes delivering the code on time and on budget frustratingly (and unnecessarily) difficult.&lt;BR&gt;&lt;BR&gt;3) Slowness to develop:&amp;nbsp; This was a real show stopper.&amp;nbsp; Every time a change is made in the COM object code (the COM object has to be completely recompiled from scratch, which took 2-3 minutes on a state of the art machines (This # could vary depending on the size of your COM objects).&amp;nbsp; Also, many times IIS would lock the COM object .dll, &amp;nbsp;so in addition, IIS had to be stopped and restarted too, which&amp;nbsp;took another minute or two.&amp;nbsp; (The latter&amp;nbsp;might be alleviated with object pooling, but all the other negatives forced us to abandon COM before even looking at this possibility). &lt;BR&gt;&lt;BR&gt;How does this affect things?&amp;nbsp; When code is created, it is never right the first time.&amp;nbsp; Even creating a single function is an iterative process where it's coded, run, bugs are removed, and the process repeated.&amp;nbsp; A typically complex function created by a top notch developer might require 3-4 iterations...and an average developer might require 10,15 or more.&amp;nbsp;&amp;nbsp; Being able to iterate quickly is what allows you to deliver it on time and on budget.&amp;nbsp; If creating just a single function requires 9 more minutes for your "star" developer and 30 more minutes for your average developers, you are going to have problems.&amp;nbsp; It is FRUSTRATINGLY difficult to develop under these circumstances and try to&amp;nbsp;meet time and budget commitments.&lt;/P&gt;
&lt;P&gt;I tried to explain to the Microsoft systems engineer why this was impractical, but simply got the standard "spiel" repeated to me that COM objects were wonderful and the way to go.&amp;nbsp; Obviously he believed something he read from a KB article, more than me, who he did not realize had personal experience with this supposed "solution".&amp;nbsp; &lt;BR&gt;&lt;BR&gt;&lt;SPAN&gt;&lt;FONT face="Times New Roman" size=3&gt;Conclusion: If you develop a web app with any sophisticiation or any size, ASP (classic ASP) is NOT a suitable or scalable&amp;nbsp;environment for you.&amp;nbsp; Instead go to a non Microsoft platform.&amp;nbsp; If you choose to say with Microsoft, choose the newer ASP.NET.&lt;BR&gt;&lt;BR&gt;Ian Ippolito&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;img src="http://rentacoder.com/CS/aggbug.aspx?PostID=448" width="1" height="1"&gt;</description><category domain="http://rentacoder.com/CS/blogs/real_life_it/archive/category/1002.aspx">Systems</category></item><item><title>SQL Server 2005: Are your batteries half full or half empty?</title><link>http://rentacoder.com/CS/blogs/real_life_it/archive/2006/03/17/447.aspx</link><pubDate>Sat, 18 Mar 2006 00:21:00 GMT</pubDate><guid isPermaLink="false">2b679553-572d-4457-89da-485055e17287:447</guid><dc:creator>admin</dc:creator><slash:comments>0</slash:comments><comments>http://rentacoder.com/CS/blogs/real_life_it/comments/447.aspx</comments><wfw:commentRss>http://rentacoder.com/CS/blogs/real_life_it/commentrss.aspx?PostID=447</wfw:commentRss><description>&lt;P&gt;Microsoft is running an ad campaign showing skyscraper&amp;nbsp;sized batteries labeled "SQL Server 2005" plugged into enormous buildings.&amp;nbsp; The message is obviously that this database is designed for big companies and serious mission critical systems. &lt;BR&gt;&lt;BR&gt;&lt;A href="/CS/photos/general_photo_gallery/picture500.aspx" target=_blank&gt;&lt;IMG src="/CS/photos/general_photo_gallery/images/500/original.aspx" border=0&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;SQL 2005 is packed with impressive new features...too many to mention here.&amp;nbsp; Some of them are truly awesome...like the new reporting capabilities which come as part of the purchase price, rather than having to buy a seperate system.&amp;nbsp; Unfortuntely my experience with running the current version on a mission critical system (PRE Service Pack 1)&amp;nbsp;has not been as impressive as I was hoping.&lt;BR&gt;&lt;BR&gt;Along with the upgrade from SQL Server 2000 to 2005, we also simultaneously upgraded the hardware substantially.&amp;nbsp; We went from a 32-bit dual processor box to an expensive "screamer"...a 64-bit quad processor box with dual core (so from&amp;nbsp;two 32 bit processors to virtually eight 64 bit processors).&amp;nbsp; And yet performance in SQL Server 2005 is no better than in 2000.&amp;nbsp; And in some cases it's worse.&amp;nbsp; What as going on?&lt;/P&gt;
&lt;P&gt;A part&amp;nbsp;of the problem&amp;nbsp;was the Database Tuning Advisor (DTA).&amp;nbsp;SQL 2005 has so many cool new features, but they are useless if you can't optimize the database.&amp;nbsp; And that lack of optimization has caused increased timeouts, deadlocks and alot of personal user dissatisifaction with our service.&amp;nbsp; The first problem is that the advisor takes a LONG time to run.&amp;nbsp; Just tuning a query used to take a few seconds in 2000...now it goes through a multi step process lasting 4-5 minutes.&amp;nbsp; Running a real workload is worse.&amp;nbsp; But that's something you can learn to live with.&amp;nbsp; But the problem is that the long wait times come with an unexpected companion...timeouts and deadlocks.&amp;nbsp;&amp;nbsp; The old 2000 let you analyze it "live" without any reprecusions (which I did may times).&amp;nbsp; But don't make the mistake of running the current version of DTA on a database with a decent load on it.&amp;nbsp;&amp;nbsp;I don't know what DTA does, but every time I did it, it started terminating 1/2 of my users as deadlock victims so it could do it's business.&amp;nbsp;And&amp;nbsp;after about 45 minutes of this, it got worse becuase it just HUNG.&amp;nbsp; And it was a bad hang too...becuase just restarting the service wasn't enough.&amp;nbsp; I had to physically reboot the machine to allow&amp;nbsp;clients to reconnect to it.&amp;nbsp; It takes a long time for that beast of a machine to reboot (about 7 minutes), and the users were not pleased with me.&amp;nbsp; Thank you DTA...may I have another?&lt;/P&gt;
&lt;P&gt;Unfortunately, DTA's answers to that question is "yes you may!".&amp;nbsp; There is the abilty to run DTA on a remote server to "lessen the load" on the production server (according to the MSFT documentation).&amp;nbsp; In my case, load wasn't&amp;nbsp;really the problem...the CPU never went above 50% on the production machine.&amp;nbsp; It's the hanging that was a problem.&amp;nbsp; Anyway, I discovered that for whatever reason, remote tuning stopped the hangs.&amp;nbsp; But this only led to more problems.&lt;/P&gt;
&lt;P&gt;At first I could never complete even a single tuning session becuase I would get a cryptic "Tuning process exited unexpectedly. (DTAEngine)".&amp;nbsp; I was reduced to hitting "stop" at random points before it finished to get partial recommendations...anything to stop any of those timeouts.&amp;nbsp; But I needed a real solution.&amp;nbsp; So I opened a ticket with MSFT and&amp;nbsp;they confirmed&amp;nbsp;found a bug in DTA in dealing with indexed views (and is fixing it...ETA 3 weeks).&lt;BR&gt;&lt;BR&gt;So after I learned that indexed views were the culprit I thought I'd at least be able to tune it 50% by setting&amp;nbsp;DTA to tune "tables only".&amp;nbsp; Smart idea right?&amp;nbsp; Well...kind of.&amp;nbsp; It worked...sometimes.&amp;nbsp; But about 50% of the time DTA bombs out with "Index (zero based) must be greater than or equal to zero and less than the size of the argument list.&amp;nbsp; Turning process finished."&amp;nbsp; Nice and vague.&amp;nbsp; And again, the crash stops any recommendations from being made.&amp;nbsp; So yes, I had to open another Microsoft support ticket.&amp;nbsp;&amp;nbsp;I have six open right now...is that some sort of record?&amp;nbsp;Sadly I think it probably is not.&amp;nbsp; The worse thing is that Microsoft has duplicated this bug, but didn't fix it in SP1 and may not even issue a hotfix for it.&amp;nbsp; The MSFT tech explained that they cannot fix it until enough people complain about it.&amp;nbsp; So until enough people running big databases adopt SQL 2005 and run into these same issues...I am stuck dead in the water on this issue.&amp;nbsp; But until they get problems like this solved...people are not going to be moving their databases over.&amp;nbsp; A true "Catch 22".&lt;BR&gt;(update: 5/8/2006: This will be made into a post SP1 hotfix...thanks to everyone else who also complained!)&amp;nbsp; &lt;BR&gt;&lt;BR&gt;Conclusion:&lt;BR&gt;&lt;BR&gt;SQL 2005 has some awesome features.&amp;nbsp; But it doesn't do any good&amp;nbsp;your database&amp;nbsp;runs slower than the last version becuase&amp;nbsp;of the lack of DTA.&amp;nbsp; &lt;STRONG&gt;My advice to anyone that asks is to wait for Microsoft to fix these bugs with SQL Server 2005 SP1 before jumping in with anything that is mission critical.&lt;/STRONG&gt;&lt;/P&gt;Ian Ippolito&lt;A href="/CS/photos/general_photo_gallery/picture500.aspx" target=_blank&gt;&lt;/A&gt;&lt;img src="http://rentacoder.com/CS/aggbug.aspx?PostID=447" width="1" height="1"&gt;</description><category domain="http://rentacoder.com/CS/blogs/real_life_it/archive/category/1002.aspx">Systems</category></item><item><title>Beware the Ides of ISA Service Pack 2 (SP2)</title><link>http://rentacoder.com/CS/blogs/real_life_it/archive/2006/03/17/446.aspx</link><pubDate>Sat, 18 Mar 2006 00:18:00 GMT</pubDate><guid isPermaLink="false">2b679553-572d-4457-89da-485055e17287:446</guid><dc:creator>admin</dc:creator><slash:comments>0</slash:comments><comments>http://rentacoder.com/CS/blogs/real_life_it/comments/446.aspx</comments><wfw:commentRss>http://rentacoder.com/CS/blogs/real_life_it/commentrss.aspx?PostID=446</wfw:commentRss><description>&lt;P&gt;I've&amp;nbsp;confirmed that the SendAcceptEncodingHeader metabase setting that USED to work pre ISA (Internet Security and Acceleration Server) SP2 and&amp;nbsp;allowed IIS to pass through the compression headers for gzip, is no longer working with SP2 (and passed this on to Microsoft).&amp;nbsp;&amp;nbsp; &lt;/P&gt;
&lt;P&gt;The other option, is to of course use ISA SP2's spiffy new (and highly touted) compression.&amp;nbsp; So I turned it on to give a run. It ran fine...for about 20 minutes.&amp;nbsp; Then it crashed with an error of : "ISA Server was unable to decompress a response body from /RentACoder because the following error occurred: 0x80070008."&amp;nbsp; I tried turning off the decompression (unchecked the checkbox on the 3rd tab)...and still got the same crash after about 30 minutes. &lt;/P&gt;
&lt;P&gt;So I brought this up to Microsoft support, and the engineer passed on that Jim (the ISA manager) said that the compression features were designed for branch offices.&amp;nbsp; Nice to know about that qualifier in advance, huh? :)&lt;BR&gt;&lt;BR&gt;Unfortuantely I'm stuck between a rock and hard place&amp;nbsp;with SP2.&amp;nbsp; I installed it becuase Microsoft reworked their handling of large attachments, and they felt it would fix the ISA crashes I was having every 1-4 weeks.&amp;nbsp; And it looks like it is doing the trick (no crash for 3.5 weeks now).&amp;nbsp; But now my bandwidth costs are going to be 2x-4x higher this month than they should be due to ISA SP2's new "feature".&amp;nbsp; I can't win either way. (The Microsoft tech I'm dealing with, Masoud,&amp;nbsp;said he'll try to get duplicate this and get something going in a week or so...I hope he can&amp;nbsp;pull it off).&lt;/P&gt;
&lt;P&gt;However, it could be worse.&amp;nbsp; I've done some reading on newsgroups and&amp;nbsp;Microsoft is slammed with other problems in this SP2 concerning compression in the opposite direction...people browsing from behind ISA SP2 seem to have problems.&amp;nbsp; Thankfully that isn't my situation too.&lt;/P&gt;
&lt;P&gt;Ian Ippolito&lt;BR&gt;&lt;A href="http://www.RentACoder.com"&gt;http://www.RentACoder.com&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;4/27/2006: UPDATE: There is a workaround to fix this problem.&amp;nbsp; If you completely disable the new and "improved compression .dll that SP2 has so generously forced upon you (but that doesn't work)...the compression metabase setting works again!&amp;nbsp; To do this:&lt;BR&gt;Go to "configuration", "add-in", "web filters" tab.&amp;nbsp; Then disable "compression filter".&amp;nbsp; Viola...enjoy!&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;Ian Ippolito&lt;/P&gt;&lt;img src="http://rentacoder.com/CS/aggbug.aspx?PostID=446" width="1" height="1"&gt;</description><category domain="http://rentacoder.com/CS/blogs/real_life_it/archive/category/1002.aspx">Systems</category></item></channel></rss>