﻿<?xml version='1.0' encoding='UTF-8'?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>SQLServerCentral / Discuss Content Posted by Leo Peysakhovich / Article Discussions / Article Discussions by Author  / Performance Tips Part 1 / Latest Posts</title><generator>InstantForum.NET v2.9.0</generator><description>SQLServerCentral</description><link>http://www.sqlservercentral.com/Forums/</link><webMaster>notifications@sqlservercentral.com</webMaster><lastBuildDate>Sat, 18 May 2013 08:44:15 GMT</lastBuildDate><ttl>20</ttl><item><title>RE: Performance Tips Part 1</title><link>http://www.sqlservercentral.com/Forums/Topic164150-163-1.aspx</link><description>&lt;P&gt;&lt;FONT style="BACKGROUND-COLOR: #d4d0c8"&gt;In the archiving situation, I think that it is missing a transaction (or else you risk losing log events, between the insert into the archive and the truncate). &lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT style="BACKGROUND-COLOR: #d4d0c8"&gt;I don't agree that it is a one time solution, because you normally archive by year, so every year you create a new table (if it's only for archiving, it's more manageable).&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT style="BACKGROUND-COLOR: #d4d0c8"&gt;André Cardoso&lt;/FONT&gt;&lt;/P&gt;</description><pubDate>Wed, 08 Mar 2006 05:34:00 GMT</pubDate><dc:creator>André Cardoso</dc:creator></item><item><title>RE: Performance Tips Part 1</title><link>http://www.sqlservercentral.com/Forums/Topic164150-163-1.aspx</link><description>&lt;DIV&gt;&lt;SPAN class=060423022-08032005&gt;&lt;FONT face=Arial color=#0000ff size=2&gt;Good catch.&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN class=060423022-08032005&gt;&lt;FONT face=Arial color=#0000ff size=2&gt;&lt;/FONT&gt;&lt;/SPAN&gt; &lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN class=060423022-08032005&gt;&lt;FONT face=Arial color=#0000ff size=2&gt;It should be &lt;/FONT&gt;&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN class=060423022-08032005&gt;&lt;FONT face=Arial color=#0000ff size=2&gt;&lt;/FONT&gt;&lt;/SPAN&gt; &lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN class=060423022-08032005&gt;insert into Call_Log_Event (call_log_id, event_desc, event_cd , eventdt, archivedt)select call_log_id, event_desc, event_cd , eventdt, getdate()  from Call_Log_Event_Archive  where datediff(dd,eventdt, getdate()) &amp;lt;= 10 &lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN class=060423022-08032005&gt;&lt;/SPAN&gt; &lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN class=060423022-08032005&gt;I placed only an idea to show that many ways around to get better solution than the one (actually many people using) I described. Depend on the situation different decision may be taken. You are right.&lt;/SPAN&gt;&lt;/DIV&gt;</description><pubDate>Thu, 10 Mar 2005 18:50:00 GMT</pubDate><dc:creator>Leo Peysakhovich</dc:creator></item><item><title>RE: Performance Tips Part 1</title><link>http://www.sqlservercentral.com/Forums/Topic164150-163-1.aspx</link><description>Talking more about situation three.First, just to be completely pedantic, step 4 in your example seems to have the table names reversed, so that instead of copying the latest data back to the Call_Log_Event table, you're copying data from the (empty) Call_Log_Event table to Call_Log_Event_Archive again.  Of course, since no one else has mentioned this, maybe I'm badly misreading things.Second, in cases where there is a need to archive data, there is usually a need to do it more than once.  Your process is a one-time solution to what will probably become a repeating problem.You could continue by inserting the current data from Call_Event_Log into Call_Event_Log_Archive as you've done in this instant.  However, as the archive table grows larger and larger, I believe you will hit a point where searching for the records to be copied back, then removed will take much longer than simply deleting the records in the first place.  It's possible that, with proper indexing, this wouldn't be significantly worse for some time, but I believe it would happen.Of course, if one of the concerns is how fast you can release Call_Event_Log for use, your method still might work well if the Call_Event_Log data was always written to a temp table instead of to the full Archive table.  Restore the data from the temp table to Call_Event_Log first, commit, then write the data to be moved to Call_Event_Log_Archive, and drop the temp teble.  This would almost certainly be slower than your solution overall (two writes of the archived data), but you can lock one table at a time, keeping things flowing as freely as possible.  As you point out, the time when critical resources are locked can be far more important than the actual time it takes to complete an operation.</description><pubDate>Thu, 10 Mar 2005 16:45:00 GMT</pubDate><dc:creator>RD Francis</dc:creator></item><item><title>RE: Performance Tips Part 1</title><link>http://www.sqlservercentral.com/Forums/Topic164150-163-1.aspx</link><description>Let it be this way. Next time I will use your loop control when I can't awoid a big looping structure. Good solution. I am fine with all solutions as far as they are not completely off a practical use. I have seing many solutions that are good in theory but do not really help in reality. They are way off the practical use.</description><pubDate>Wed, 09 Mar 2005 19:21:00 GMT</pubDate><dc:creator>Leo Peysakhovich</dc:creator></item><item><title>RE: Performance Tips Part 1</title><link>http://www.sqlservercentral.com/Forums/Topic164150-163-1.aspx</link><description>&lt;P&gt;Definitely a set-based solution is always best, and you're right that many loops can be converted into set-based processing.&lt;/P&gt;&lt;P&gt;That's not what we were talking about, though; we were talking about replacements for cursors &lt;U&gt;when a loop is needed&lt;/U&gt;.  I always appreciate seeing a "while" loop instead of a cursor (and i appreciate seeing a set-based solution even more), as they are cleaner and (I think) easier to read.  I commend you on this, but I was also pointing out that using a "break" instead of checking variables is more efficient, especially when using "Select min, max" to set the loop control variables.&lt;/P&gt;&lt;P&gt;I'm not trying to piss you off or anything...&lt;/P&gt;&lt;P&gt;cl&lt;/P&gt;</description><pubDate>Wed, 09 Mar 2005 19:11:00 GMT</pubDate><dc:creator>Calvin Lawson</dc:creator></item><item><title>RE: Performance Tips Part 1</title><link>http://www.sqlservercentral.com/Forums/Topic164150-163-1.aspx</link><description>&lt;P&gt;I am not defencive, but trying to be realistic. If I need over 200 -500 loops then I need to look an alternative to the loop solution and in most cases I was able to find it. For example, instead of writing a loop to get permission for all tables  &lt;/P&gt;&lt;P&gt;grant SELECT on table1 to XYZ&lt;/P&gt;&lt;P&gt;Grant SELECT on table2 to XYZ&lt;/P&gt;&lt;P&gt;...........................................&lt;/P&gt;&lt;P&gt;it can be achived by &lt;/P&gt;&lt;P&gt; &lt;/P&gt;&lt;P&gt;declare @cmd varchar(8000)&lt;/P&gt;&lt;P&gt;set @cmd = ''&lt;/P&gt;&lt;P&gt;select @cmd = @cmd + '&lt;/P&gt;&lt;P&gt;grant SELECT on ' + name + ' on XYZ '  from sysobjects where type = 'U'&lt;/P&gt;</description><pubDate>Wed, 09 Mar 2005 19:04:00 GMT</pubDate><dc:creator>Leo Peysakhovich</dc:creator></item><item><title>RE: Performance Tips Part 1</title><link>http://www.sqlservercentral.com/Forums/Topic164150-163-1.aspx</link><description>&lt;P&gt;Actually...it is significantly different, per my optimizer it costs 2.5% of the total cost of both (although this includes creating the table variable, which I would HOPE you had in for testing purposes only).&lt;/P&gt;&lt;P&gt;I would agree that this is not significant if it's under a 100 loops or so (which is the case in your example), but it is significant with more loops.  I might add, under a 100 loops there is no significant difference between a cursor and either while loop.&lt;/P&gt;&lt;P&gt;I certainly wasn't saying you should modify your existing code.  But since your article was about optimization, I figured you'd be interested.  Seems like you are a little defensive instead.  Oh well...&lt;/P&gt;&lt;P&gt;cl&lt;/P&gt;&lt;P&gt; &lt;/P&gt;</description><pubDate>Wed, 09 Mar 2005 17:51:00 GMT</pubDate><dc:creator>Calvin Lawson</dc:creator></item><item><title>RE: Performance Tips Part 1</title><link>http://www.sqlservercentral.com/Forums/Topic164150-163-1.aspx</link><description>&lt;P&gt;Possible that optimizer shows that the break is more effective but it is like 10 or 10.01 miles/gal. Is it different? For testing purpose  on factory - yes. In real world ????? When I am working, I am trying to cut worst parts and advice developers to focus on important changes. This one I am not consider as important because there is no major time cut and it is not influence another processes.&lt;/P&gt;</description><pubDate>Wed, 09 Mar 2005 17:07:00 GMT</pubDate><dc:creator>Leo Peysakhovich</dc:creator></item><item><title>RE: Performance Tips Part 1</title><link>http://www.sqlservercentral.com/Forums/Topic164150-163-1.aspx</link><description>&lt;DIV&gt;&lt;TABLE class=quote cellSpacing=1 cellPadding=5&gt;&lt;TBODY&gt;&lt;TR&gt;&lt;TD vAlign=top noWrap width=11&gt;&lt;IMG height=13 alt=quote src="http://www.sqlservercentral.com/forums/images/quoteicon.gif" width=11 align=absMiddle&gt;&lt;/TD&gt;&lt;TD width="99%"&gt;In the real world I have some issues with object renaming. I have seeing the cases where after renaming an object and creating another one with the same name some applications start erroring with message that it can't find an object (even I can see it and work with it in Query Analyzer). Personally, I do avoid renaming in production databases.&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;P&gt;&lt;P&gt;Per BOL..."&lt;STRONG&gt;Important&lt;/STRONG&gt;  After renaming stored procedures and views, flush the procedure cache to ensure all dependent stored procedures and views are recompiled."&lt;/P&gt;&lt;P&gt;Notice the "DBCC FREEPROCCACHE" at the end of the rename script.&lt;/P&gt;&lt;P&gt;On another topic, I noticed you didn't comment on the different while loop.  What do you think about using a break instead of min and max variables?  If you check the optimizer it's definitely more efficient.&lt;/P&gt;&lt;/DIV&gt;</description><pubDate>Wed, 09 Mar 2005 12:25:00 GMT</pubDate><dc:creator>Calvin Lawson</dc:creator></item><item><title>RE: Performance Tips Part 1</title><link>http://www.sqlservercentral.com/Forums/Topic164150-163-1.aspx</link><description>&lt;P&gt;Thanks for the warm words. I do like good solutions and your's is good for the discussion. I do follow your's advise while I am doing quick and dirty tests. In the real world I have some issues with object renaming. I have seeing the cases where after renaming an object and creating another one with the same name some applications start erroring with message that it can't find an object (even I can see it and work with it in Query Analyzer). Personally, I do avoid renaming in production databases.&lt;/P&gt;&lt;P&gt;Second part will be soon. It is under review.&lt;/P&gt;</description><pubDate>Wed, 09 Mar 2005 09:40:00 GMT</pubDate><dc:creator>Leo Peysakhovich</dc:creator></item><item><title>RE: Performance Tips Part 1</title><link>http://www.sqlservercentral.com/Forums/Topic164150-163-1.aspx</link><description>&lt;P&gt;I liked your article, so I hope you don't think I was being criticle. You gave some good ideas about things that can effect performance. My thought on renaming tables was simply adding to the discussion, not trying to say there was a better way. It seemed reasonable that instead of moving 3,000,000 records, it would be more effecient to move 10,000 and renaming would allow that. Clearly, any real world system may have additional complexities such as you pointed out.&lt;/P&gt;&lt;P&gt;Again, it was a good article both in its content and in the discussion it created. I'm looking forward to part two.&lt;/P&gt;</description><pubDate>Wed, 09 Mar 2005 06:59:00 GMT</pubDate><dc:creator>SW21_Bob</dc:creator></item><item><title>RE: Performance Tips Part 1</title><link>http://www.sqlservercentral.com/Forums/Topic164150-163-1.aspx</link><description>&lt;P&gt;I do understand your point. But as an example I get criteria (not the best one) just to illustrate the point. &lt;/P&gt;&lt;P&gt;If you look my first performance article &lt;A href="http://www.sqlservercentral.com/columnists/lPeysakhovich/overviewofperformance.asp"&gt;http://www.sqlservercentral.com/columnists/lPeysakhovich/overviewofperformance.asp&lt;/A&gt;)&lt;/P&gt;&lt;P&gt;you will see that I am using the idea you suggesting to populate a seed table with the PK values&lt;/P&gt;</description><pubDate>Tue, 08 Mar 2005 17:59:00 GMT</pubDate><dc:creator>Leo Peysakhovich</dc:creator></item><item><title>RE: Performance Tips Part 1</title><link>http://www.sqlservercentral.com/Forums/Topic164150-163-1.aspx</link><description>&lt;P&gt;Yes, I can do it. Rename indexes, tables, databases, and so on. &lt;/P&gt;&lt;P&gt;But the main point of the article is to show that a simple change may have a big effect. And another point, that developer who is writing an archiving process have no permissions to rename objects.  Plus this is only a small part of the process. Process consists with tonns of pages of code and this is the only one small part of the logic.&lt;/P&gt;</description><pubDate>Tue, 08 Mar 2005 17:49:00 GMT</pubDate><dc:creator>Leo Peysakhovich</dc:creator></item><item><title>RE: Performance Tips Part 1</title><link>http://www.sqlservercentral.com/Forums/Topic164150-163-1.aspx</link><description>&lt;P&gt;You can rename indexes and other objects:&lt;/P&gt;&lt;P&gt;use pubs&lt;/P&gt;&lt;P&gt;if object_ID('test_rename_HIS') is not null drop table test_rename_HISif object_ID('test_rename_ARC') is not null drop table test_rename_ARC&lt;/P&gt;&lt;P&gt;create table test_rename_HIS  (ID int Not Null constraint PK_HIS Primary Key,   Name varchar(255))&lt;/P&gt;&lt;P&gt;go&lt;/P&gt;&lt;P&gt;create index I_HIS on test_rename_HIS (Name)&lt;/P&gt;&lt;P&gt;go&lt;/P&gt;&lt;P&gt;exec sp_rename  @objname =  'test_rename_HIS' ,     @newname =  'test_rename_ARC'  ,    @objtype =  'Object'&lt;/P&gt;&lt;P&gt;go&lt;/P&gt;&lt;P&gt;exec sp_rename  @objname =  'PK_HIS' ,     @newname =  'PK_ARC'  ,    @objtype =  'Object'&lt;/P&gt;&lt;P&gt;go&lt;/P&gt;&lt;P&gt;exec sp_rename  @objname =  'test_rename_ARC.I_HIS' ,     @newname =  'I_ARC'  ,    @objtype =  'Index'&lt;/P&gt;&lt;P&gt;go&lt;/P&gt;&lt;P&gt;DBCC FREEPROCCACHE&lt;/P&gt;</description><pubDate>Tue, 08 Mar 2005 16:30:00 GMT</pubDate><dc:creator>Calvin Lawson</dc:creator></item><item><title>RE: Performance Tips Part 1</title><link>http://www.sqlservercentral.com/Forums/Topic164150-163-1.aspx</link><description>You right if it is the simple table in air. In our case each table has the corresponding names for the PK and indexes. For example, table t_customer will have PK named as I_PK_T_Customer_10.  Index may have a name I_IN_T_Customer_20. By renaming the table I will ruin the database standartization.</description><pubDate>Tue, 08 Mar 2005 16:05:00 GMT</pubDate><dc:creator>Leo Peysakhovich</dc:creator></item><item><title>RE: Performance Tips Part 1</title><link>http://www.sqlservercentral.com/Forums/Topic164150-163-1.aspx</link><description>&lt;P&gt;Very nice decision. But in my case this is just a quick example. &lt;/P&gt;&lt;P&gt;This article I placed as a general guideline for the developers because I am tired with obvious performance glitches. Probably some parts can be done better. But my main point was to show that small thoughts can make a difference.&lt;/P&gt;</description><pubDate>Tue, 08 Mar 2005 16:01:00 GMT</pubDate><dc:creator>Leo Peysakhovich</dc:creator></item><item><title>RE: Performance Tips Part 1</title><link>http://www.sqlservercentral.com/Forums/Topic164150-163-1.aspx</link><description>&lt;P&gt;Good solution as well. And achieve the same point. &lt;/P&gt;&lt;P&gt;Second comment. I am writing this article mainly for the application developers and/or report writers. Most of them have no idea what mean effect of concurrency &amp;amp; transaction isolation. But they need a general guide line to make better performance.&lt;/P&gt;</description><pubDate>Tue, 08 Mar 2005 15:55:00 GMT</pubDate><dc:creator>Leo Peysakhovich</dc:creator></item><item><title>RE: Performance Tips Part 1</title><link>http://www.sqlservercentral.com/Forums/Topic164150-163-1.aspx</link><description>For number 3, rather than moving the data into the archive table, rename the history table to archive then move the relatively few records into a new history table. This should work OK since you said the tables have no defined relationships. Or does renaming a table do things internally that I don't know about that make this a bad idea?</description><pubDate>Tue, 08 Mar 2005 13:28:00 GMT</pubDate><dc:creator>SW21_Bob</dc:creator></item><item><title>RE: Performance Tips Part 1</title><link>http://www.sqlservercentral.com/Forums/Topic164150-163-1.aspx</link><description>&lt;P&gt;Pretty good article, with some nice tips.  Regarding PW's note, it's a valid option, but no real performance increase over using variables.&lt;/P&gt;&lt;P&gt;Situation 3 looks dicey, though.  I understand what you're trying to do, and if your "Where" clause is expensive it could perform better.  What you really need to do in this case is populate a seed table with the PK values, then use this to move rows around.  It will perform better than moving the whole row one extra time, especially if it's a big row.&lt;/P&gt;&lt;P&gt;Situation 4 is nice...I've been harping on the uselessness of fast forward cursors for a "while" (oops...&lt;img src='images/emotions/smile.gif' height='20' width='20' border='0' title='Smile' align='absmiddle'&gt;.  I usually use a different form, though; The performance is significantly better.&lt;/P&gt;&lt;P&gt;----------------------------------------------------------------------------------&lt;/P&gt;&lt;P&gt;declare @name sysname&lt;/P&gt;&lt;P&gt;While 1 = 1&lt;/P&gt;&lt;P&gt; begin&lt;/P&gt;&lt;P&gt;   select top 1 @Name = name  from master..sysdatabases  where Name &amp;gt; isnull(@Name, '') order by Name&lt;/P&gt;&lt;P&gt; if @@RowCount = 0 Break&lt;/P&gt;&lt;P&gt; select @Name Name&lt;/P&gt;&lt;P&gt; end&lt;/P&gt;</description><pubDate>Tue, 08 Mar 2005 12:22:00 GMT</pubDate><dc:creator>Calvin Lawson</dc:creator></item><item><title>RE: Performance Tips Part 1</title><link>http://www.sqlservercentral.com/Forums/Topic164150-163-1.aspx</link><description>&lt;P&gt;Situation #1&lt;/P&gt;&lt;P&gt;Use a Derived Table (Or a Common Table Expression [CTE] in SqlServer 2005) and lose the variables:&lt;/P&gt;&lt;P&gt;SELECT   t1.col1, t1.col2, dt.col1, dt.col2  FROM   Customer t1 CROSS JOIN   (    SELECT TOP 1 col1, col2    FROM GeneralInfo t2 \) dtWHERE t1.status &amp;gt; 0&lt;/P&gt;&lt;P&gt;Situation #2&lt;/P&gt;&lt;P&gt;Discussion is incomplete without mentioning effect of concurrency &amp;amp; transaction isolation. Yes, splitting into smaller queries may reduce lock hold time and reduce contention, but what does that gain if the end result is *different* than 1 large statement, because other processes changed data between the steps of a broken out process ?&lt;/P&gt;&lt;P&gt; &lt;/P&gt;&lt;P&gt; &lt;/P&gt;</description><pubDate>Tue, 08 Mar 2005 10:42:00 GMT</pubDate><dc:creator>PW-201837</dc:creator></item><item><title>Performance Tips Part 1</title><link>http://www.sqlservercentral.com/Forums/Topic164150-163-1.aspx</link><description>Comments posted to this topic are about the content posted at &lt;A HREF="http://www.sqlservercentral.com/columnists/lPeysakhovich/performancetipspart1.asp"&gt;http://www.sqlservercentral.com/columnists/lPeysakhovich/performancetipspart1.asp&lt;/A&gt;</description><pubDate>Fri, 25 Feb 2005 10:31:00 GMT</pubDate><dc:creator>Leo Peysakhovich</dc:creator></item></channel></rss>