<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://sqlservernation.com/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><title type="html">Administration</title><subtitle type="html" /><id>http://sqlservernation.com/blogs/admin/atom.aspx</id><link rel="alternate" type="text/html" href="http://sqlservernation.com/blogs/admin/default.aspx" /><link rel="self" type="application/atom+xml" href="http://sqlservernation.com/blogs/admin/atom.aspx" /><generator uri="http://communityserver.org" version="4.1.40407.4157">Community Server</generator><updated>2009-03-24T14:56:00Z</updated><entry><title>Whats running on my SQL Server? Part 1</title><link rel="alternate" type="text/html" href="/blogs/admin/archive/2009/09/23/whats-running-on-my-sql-server.aspx" /><id>/blogs/admin/archive/2009/09/23/whats-running-on-my-sql-server.aspx</id><published>2009-09-23T23:27:00Z</published><updated>2009-09-23T23:27:00Z</updated><content type="html">&lt;p&gt;SQL Server 2005 introduced some exciting new tools for viewing what statements are running on your database instance.&amp;nbsp; At the base of these tools are the new dynamic management views (DMV) that allows you to view SQL statements executing based on connection.&amp;nbsp; Management Studio uses these views to supply the end user with some pretty informative reports for executions.&amp;nbsp; Today Im going to take a look a couple of the views that are the cornerstone of acquiring this information.&lt;/p&gt;
&lt;p&gt;The view I&amp;#39;ll look at today is sys.dm_exec_requests.&amp;nbsp; This view returns one record for each request that is executing inside of the database engine.&amp;nbsp; I can query this view with a filter of any session_id &amp;gt; 50 to return all user-level sessions.&amp;nbsp; This view returns a lot of performance data related to the executing script.&amp;nbsp; For example, I can view the status of the command, if it is currently being blocked, the reads and writes incurred by the statement and the query plan.&amp;nbsp; One great thing about this DMV is that it contains a hash field (sql_handle)&amp;nbsp;that contains the actual SQL statement that is being executed.&amp;nbsp; This is very useful because it lets me determine the exact SQL statement that is being called.&lt;/p&gt;
&lt;pre style="font-size:12px;overflow:auto;width:100%;color:#000000;line-height:14px;font-family:Andale Mono, Lucida Console, Monaco, fixed, monospace;background-color:#eee;border:#999999 1px dashed;padding:5px;"&gt;&lt;code&gt;SELECT rq.session_id, rq.start_time, t.text 
FROM sys.dm_exec_requests rq
CROSS APPLY sys.dm_exec_sql_text(sql_handle) t
WHERE session_id &amp;gt; 50 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;In the above script, I use the sys.dm_exec_sql_text DMV (function) and pass the the sql_handle field to it.&amp;nbsp; This DMV returns the actual SQL text being ran.&amp;nbsp; If I wanted to, I could easily rearrange the above SQL snippet to replace the DBCC INPUTBUFFER command that we are all accustomed to using to determine what SQL a current spid is using.&amp;nbsp; I&amp;#39;ll show you how you can easily rewrite DBCC INPUTBUFFER in a future post so that it is a little bit more useful...&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://sqlservernation.com/aggbug.aspx?PostID=178" width="1" height="1"&gt;</content><author><name>TimChapman</name><uri>http://sqlservernation.com/members/TimChapman/default.aspx</uri></author></entry><entry><title>Fix for: Cannot open user default database.  Login Failed.</title><link rel="alternate" type="text/html" href="/blogs/admin/archive/2009/09/22/fix-for-cannot-open-user-default-database-login-failed.aspx" /><id>/blogs/admin/archive/2009/09/22/fix-for-cannot-open-user-default-database-login-failed.aspx</id><published>2009-09-23T01:59:00Z</published><updated>2009-09-23T01:59:00Z</updated><content type="html">&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;In this article I will show you some options to recover from the error &amp;quot;Cannot open user default database.&amp;nbsp; Login Failed&amp;quot;.&lt;/p&gt;
&lt;p&gt;How does this happen?&amp;nbsp; This happens when a login has a default
database set, and that database is deleted.&amp;nbsp; When you open any of the
Microsoft database tools (like SQL Server Management Studio or Query
Anaylzer), it automatically attaches you to the default database.&amp;nbsp; The
problem is, that if that database has been deleted, you get the
following error message.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://sqlservernation.com/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/admin.2009.09.22.default_5F00_db_5F00_deleted/3060.error1.png" style="max-width:550px;" border="0" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;There are a few things that you can do to recover from this.&amp;nbsp; You
can login with a different account and change the default database for
the effected login.&amp;nbsp; You can do this in one of two ways.&amp;nbsp; Via T-SQL and
the SSMS interface.&lt;/p&gt;
&lt;p&gt;Step 1) Right click the effected user and choose properties.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://sqlservernation.com/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/admin.2009.09.22.default_5F00_db_5F00_deleted/8233.change_5F00_SSMS.png" style="max-width:550px;" border="0" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Step 2) Change the default database to a different database.&amp;nbsp; The
default for all newly created users is master unless a different
database is defined so that&amp;#39;s the safest choice.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://sqlservernation.com/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/admin.2009.09.22.default_5F00_db_5F00_deleted/2870.change_5F00_SSMS_5F00_2.png" style="max-width:550px;" border="0" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Now what you probably know already is that SSMS will turn around and
execute SQL commands to do this.&amp;nbsp; So let&amp;#39;s just show you now how to do
this.&lt;/p&gt;
&lt;pre style="border:1px dashed #999999;padding:5px;overflow:auto;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;color:#000000;background-color:#eeeeee;font-size:12px;line-height:14px;width:100%;"&gt;&lt;code&gt;exec sp_defaultdb &amp;#39;myuser&amp;#39;, &amp;#39;master&amp;#39;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;But what if you don&amp;#39;t have a different user that can login and
change the account for you?&amp;nbsp; Or, you don&amp;#39;t have an alternative tool
that will allow you to specify the database at login time.&amp;nbsp; The command
line tools for SQL Server will allow you to specify the database which
you want to execute.&amp;nbsp; You will use the same command as above.&amp;nbsp; Let&amp;#39;s go
over it.&lt;/p&gt;
&lt;p&gt;First open the command prompt.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://sqlservernation.com/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/admin.2009.09.22.default_5F00_db_5F00_deleted/4540.cmdline1.png" style="max-width:550px;" border="0" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Next, if you don&amp;#39;t have the SQL Server binn folder in your %PATH%
then you will need to navigate to the location where you installed the
SQL Server client tools.&amp;nbsp; By default, it is &amp;quot;C:\Program Files
(x86)\Microsoft SQL Server\90\Tools\Binn&amp;gt;&amp;quot; where 90 is the folder
for the version of SQL Server installed.&amp;nbsp; Then, you will use the
command line (osql.exe or isql.exe) to issue the command to change the
default database.&lt;/p&gt;
&lt;p&gt;Since the osql command line allows you to specify the -d option to
specify the database, you can initiate the command in the master
database (or any other database that you still have access to).&lt;/p&gt;
&lt;p&gt;SQL Authentication&lt;/p&gt;
&lt;pre style="border:1px dashed #999999;padding:5px;overflow:auto;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;color:#000000;background-color:#eeeeee;font-size:12px;line-height:14px;width:100%;"&gt;&lt;code&gt;osql -Sservername\instancename -Umyuser -Pmyuser -dmaster -Q&amp;quot;sp_defaultdb &amp;#39;myuser&amp;#39;,&amp;#39;master&amp;#39;&amp;quot;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Windows Authentication&lt;/p&gt;
&lt;pre style="border:1px dashed #999999;padding:5px;overflow:auto;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;color:#000000;background-color:#eeeeee;font-size:12px;line-height:14px;width:100%;"&gt;&lt;code&gt;osql -Sservername\instancename -E -dmaster -Q&amp;quot;sp_defaultdb &amp;#39;myuser&amp;#39;,&amp;#39;master&amp;#39;&amp;quot;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre style="border:1px dashed #999999;padding:5px;overflow:auto;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;color:#000000;background-color:#99d9ea;font-size:12px;line-height:14px;width:100%;"&gt;&lt;code&gt;NOTE: There will be no output since the sp_defaultdb&lt;br /&gt;system procedure does not have any output for non-errors.&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Now that you have changed the default database, you will be able to
login to the database using the standard Microsoft tools with no errors.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://sqlservernation.com/aggbug.aspx?PostID=291" width="1" height="1"&gt;</content><author><name>BrandonGalderisi</name><uri>http://sqlservernation.com/members/BrandonGalderisi/default.aspx</uri></author><category term="Intermediate SQL" scheme="http://sqlservernation.com/blogs/admin/archive/tags/Intermediate+SQL/default.aspx" /><category term="Beginner SQL" scheme="http://sqlservernation.com/blogs/admin/archive/tags/Beginner+SQL/default.aspx" /><category term="SQL Server 2008" scheme="http://sqlservernation.com/blogs/admin/archive/tags/SQL+Server+2008/default.aspx" /><category term="SQL Server 2005" scheme="http://sqlservernation.com/blogs/admin/archive/tags/SQL+Server+2005/default.aspx" /><category term="Advanced SQL" scheme="http://sqlservernation.com/blogs/admin/archive/tags/Advanced+SQL/default.aspx" /><category term="SQL Server 2000 login" scheme="http://sqlservernation.com/blogs/admin/archive/tags/SQL+Server+2000+login/default.aspx" /></entry><entry><title>The permissions granted to user 'someDomain\someUser' are insufficient for performing this operation. (rsAccessDenied)</title><link rel="alternate" type="text/html" href="/blogs/admin/archive/2009/09/17/the-permissions-granted-to-user-somedomain-someuser-are-insufficient-for-performing-this-operation-rsaccessdenied.aspx" /><id>/blogs/admin/archive/2009/09/17/the-permissions-granted-to-user-somedomain-someuser-are-insufficient-for-performing-this-operation-rsaccessdenied.aspx</id><published>2009-09-17T10:06:00Z</published><updated>2009-09-17T10:06:00Z</updated><content type="html">&lt;p&gt;This is a very short blog post related to the administration of the SQL Server Reporting Services. This particular post is related to an installation of SQL Server 2008 reporting services on Windows Vista. &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Problem: After attempting to access the&amp;nbsp;&lt;a href="http://localhost/reportserver"&gt;http://localhost/reportserver&lt;/a&gt; the first time after SQL Server installation on Windows Vista, the SQL Server Reporting Services show the following error:&lt;br /&gt;&lt;br /&gt;&amp;quot;Reporting Services Error: The permissions granted to user&lt;br /&gt;&amp;#39;Adelso-PC\Adelso&amp;#39; are insufficient for performing this operation.&lt;br /&gt;(rsAccessDenied) Get Online Help&amp;quot;.&lt;/p&gt;
&lt;p&gt;Solution: &lt;/p&gt;
&lt;p&gt;1. Open your SSMS as an administrator. (This is very IMPORTANT! Right-click on the SQL Server Management Studio icon and then click &amp;quot;Run as Administrator&amp;quot;)&lt;/p&gt;
&lt;p&gt;2. Connect to Reporting Services...&lt;/p&gt;
&lt;p&gt;3. For Server Name field type in localhost&lt;/p&gt;
&lt;p&gt;4. After you are connected to the Reporting Server, right-click the Home directory and click Properties.&lt;/p&gt;
&lt;p&gt;5. Click on &amp;quot;Add group or user&amp;quot;, type in the user name in the following format: someDomain\someUser&lt;/p&gt;
&lt;p&gt;6. Check the appropriate checkboxes to give permissions. &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;This is all. &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://sqlservernation.com/aggbug.aspx?PostID=282" width="1" height="1"&gt;</content><author><name>sibir1us</name><uri>http://sqlservernation.com/members/sibir1us/default.aspx</uri></author><category term="SSMS" scheme="http://sqlservernation.com/blogs/admin/archive/tags/SSMS/default.aspx" /><category term="(rsAccessDenied)" scheme="http://sqlservernation.com/blogs/admin/archive/tags/_2800_rsAccessDenied_2900_/default.aspx" /><category term="The permissions granted to user are insufficient for performing this operation" scheme="http://sqlservernation.com/blogs/admin/archive/tags/The+permissions+granted+to+user+are+insufficient+for+performing+this+operation/default.aspx" /><category term="Reporting Server" scheme="http://sqlservernation.com/blogs/admin/archive/tags/Reporting+Server/default.aspx" /><category term="SSRS" scheme="http://sqlservernation.com/blogs/admin/archive/tags/SSRS/default.aspx" /></entry><entry><title>Sql2005SsmsExpressFacet - How to continue your SQL 2008 installation</title><link rel="alternate" type="text/html" href="/blogs/admin/archive/2009/08/13/sql2005ssmsexpressfacet-how-to-continue-your-sql-2008-installation.aspx" /><id>/blogs/admin/archive/2009/08/13/sql2005ssmsexpressfacet-how-to-continue-your-sql-2008-installation.aspx</id><published>2009-08-13T08:51:00Z</published><updated>2009-08-13T08:51:00Z</updated><content type="html">&lt;p&gt;Today I faced the following &lt;span style="text-decoration:underline;"&gt;problem&lt;/span&gt;: &lt;/p&gt;
&lt;p&gt;I wanted to install SQL Server 2008 on my machine, but the installation failed with the error: &amp;quot;The SQL Server 2005 Express Tools are installed. To continue, remove the SQL Server 2005 Express Tools.&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;span style="text-decoration:underline;"&gt;History&lt;/span&gt;: I had installed the Visual Studio 2005, including the SQL Express. After that I had installed the SQL Server 2005. And now I wanted to have an instance of SQL 2008. &lt;/p&gt;
&lt;p&gt;Great plan, however it didn&amp;#39;t go as smooth as intended. &lt;/p&gt;
&lt;p&gt;&lt;span style="text-decoration:underline;"&gt;Solution&lt;/span&gt;: I went to Programs and files and uninstalled the SQL Express. The SQL 2008 setup was STILL failing. &lt;/p&gt;
&lt;p&gt;After looking at the SQL install logs I found that the actual problem is in the registry. &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Slp: Sco: Attempting to open registry subkey SOFTWARE\Microsoft\Microsoft SQL Server\90\Tools\ShellSEM&lt;br /&gt;Slp: Rule &amp;#39;Sql2005SsmsExpressFacet&amp;#39; detection result: SQL 2005 Ssms EE installed=True&lt;br /&gt;Slp: Evaluating rule&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : Sql2005SsmsExpressFacet&lt;br /&gt;Slp: Rule evaluation done&amp;nbsp;&amp;nbsp; : Failed&lt;br /&gt;Slp: Rule evaluation message: The SQL Server 2005 Express Tools are installed. To continue, remove the SQL Server 2005 Express Tools.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;All I had to do is to run regedit, locate the &lt;/p&gt;
&lt;p&gt;HKEY_LOCAL_MACHINE\Software\Microsoft\Microsoft SQL Server\90\Tools\ShellSEM &lt;/p&gt;
&lt;p&gt;and &lt;span style="text-decoration:underline;"&gt;rename&lt;/span&gt; it. &lt;/p&gt;
&lt;p&gt;After this, the SQL 2008 installation will continue. &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://sqlservernation.com/aggbug.aspx?PostID=275" width="1" height="1"&gt;</content><author><name>sibir1us</name><uri>http://sqlservernation.com/members/sibir1us/default.aspx</uri></author><category term="SQL Server 2008" scheme="http://sqlservernation.com/blogs/admin/archive/tags/SQL+Server+2008/default.aspx" /><category term="Sql2005SsmsExpressFacet" scheme="http://sqlservernation.com/blogs/admin/archive/tags/Sql2005SsmsExpressFacet/default.aspx" /><category term="Express Tools are installed" scheme="http://sqlservernation.com/blogs/admin/archive/tags/Express+Tools+are+installed/default.aspx" /><category term="install fails" scheme="http://sqlservernation.com/blogs/admin/archive/tags/install+fails/default.aspx" /><category term="SQL Server 2005" scheme="http://sqlservernation.com/blogs/admin/archive/tags/SQL+Server+2005/default.aspx" /></entry><entry><title>Managing the Transaction Log for the Accidental DBA</title><link rel="alternate" type="text/html" href="/blogs/admin/archive/2009/05/28/managing-the-transaction-log-for-the-accidental-dba.aspx" /><id>/blogs/admin/archive/2009/05/28/managing-the-transaction-log-for-the-accidental-dba.aspx</id><published>2009-05-27T17:36:00Z</published><updated>2009-05-27T17:36:00Z</updated><content type="html">&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;by Mark Wills&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;Attending one of Rob Farley&amp;#39;s seminars the other day, I heard the phrase &amp;ldquo;The Accidental DBA&amp;rdquo; and fell in love with it. It got me thinking about the plight of the newcomer to SQL Server...&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;So if you are &amp;ldquo;The Accidental DBA&amp;rdquo;, or, simply new to SQL Server then there are a few concepts we can share to make your life easier. &lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;Based on the frequency of questions we see in Experts-Exchange, I thought a &amp;#39;light&amp;#39; discussion about the Transaction Log would be a good place to start.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;Microsoft&amp;#39;s SQL Server is a great database. Generally, it can look after itself, but there are one or two aspects that will need your attention. You can interactively &lt;span style="color:black;"&gt;access, configure, manage, administer, and develop&lt;/span&gt; your databases using SQL Server Management Studio (SSMS). &lt;span style="color:black;"&gt;With SSMS, the database administrator (ie you) can administer any of the components that we will be discussing. &lt;/span&gt;&amp;nbsp;Now, this article is not an introduction into SSMS, but there are a couple of tools you will need to know. For managing your database, in SSMS, use the Object explorer to right click on your database and then Properties for a range of settings and information, or Tasks to shrink or backup files. Also in Object Explorer is the Management group, expand that for Maintenance plans.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;An SQL Database is made up of three types of files, the two main files are primary data file with the extension of mdf and the transaction log file with the extension of ldf. The third is an optional secondary data file and has the extension ndf. As users add information into the database, it is stored in the data file. In turn, those transactions and database modifications can be recorded in the Transaction Log. These files are physical disk files and are built with an initial allocation of disk space. That means, you can reserve a pre-determined size for your database, and then set about filling it up (more about that later).&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;Now, the transaction log is an extremely important and sometimes neglected part of the database. Its use can mean the difference between data survival or devastation if needing to recover following a database or systems failure. &lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;The way in which your database will use the transaction log is determined by the Recovery Model. The way in which you manage the transaction log is using SQL Backup. The way in which you manage the Backup is using Maintenance Plans. And the nice thing ? It can all be automated !&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;Phew... &lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;The Recovery Model is a setting on your Database. There are three choices for Recovery Model &lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&lt;/span&gt;FULL, SIMPLE and BULK LOGGED. While it is possible to change Recovery Model at any stage, it really should be determined before you create your database. The two most often used are Simple and Full so that is what we will talk about.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;If running &amp;ldquo;SIMPLE&amp;rdquo; recovery mode then data transactions are minimally logged and a&lt;span style="color:black;"&gt;utomatically reclaims log space to keep space requirements small, essentially eliminating the need to manage the transaction log&lt;/span&gt;. If running &amp;ldquo;FULL&amp;rdquo; recovery mode then individual transactions and database modifications are fully logged in the transaction log, but then you will need to manage the log file. &lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;The idea behind FULL recovery mode is that you can recover from a failure up to a point in time &lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&lt;/span&gt;by applying transaction log backups to the last full backup. Whereas recovering from a SIMPLE recovery model means going to the last full backup. So, your choice of recovery model needs to be considered in terms of your business dependency on the volume (or existence) of data that can be recovered when restoring from backup. &lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;There are a few backup options including Full backup, Differential Backup and Transaction Log backups using the internal Backup command / facility within SQL. When DBAs talk about a backup, it is typically the SQL backup that they are most likely referring to - not the physical disk backup (which is also a crucial part of your DR plan). When restoring a database, it is the SQL backup that you will need to restore from.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;Backups are crucial part of managing your transaction logs in a FULL recovery mode. Regardless or recovery model, you do need to run Full backups, the frequency really depends on the type and volume of activity. For a typical office environment, that would most likely be every night. Then for FULL recovery, run transaction log backups during the day at regular and frequent intervals - most common are multiples of 15 minutes (ie every quarter hour, half hour, hourly etc). That helps keep the transaction log clean by truncating those transactions that are now secured in the transaction log backup and so releases that space (ie inside the file), ready to accept new transactions. In FULL recovery, it is only the Transaction log backups that will make a difference to the content of the transaction log, without them, the transaction log will continue to grow.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;There are two other Backup options Differential and Copy Only. Differential backups &lt;span style="color:black;"&gt;are smaller and faster to create than the base of a full backup being just the changes since last full backup. Using differential backups can speed up the process of making frequent backups to decrease the risk of data loss. At restore time, the full backup is restored first, followed by the most recent differential backup. Copy Only is a &amp;ldquo;special&amp;rdquo; back up normally a once off event that will not impact the state of any other scheduled backup operations.&lt;br style="mso-special-character:line-break;" /&gt;&lt;br style="mso-special-character:line-break;" /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;Really, the frequency with which backups are taken needs to reflect the Business&amp;#39;s ability to cope with data loss. The big attraction with full recovery is that it records the transactions in the transaction log which can be (progressively) applied to the last full backup. The greater the frequency, the fewer the transactions (relatively speaking) and so the less resources required to take the backup, and the greater likelihood of recovery to a point in time prior to failure.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;Now, with all that activity, how is the DBA meant to manage ? Enter, stage right, the Maintenance Plan. The maintenance plan is part of SQL Server and found in the Management object in SSMS. These plans can be scheduled using SQL Server Agent to run automatically (not in the Express edition, but there are alternatives). The maintenance plan can also perform a variety of other jobs, such as removing old backups, database &amp;lsquo;housekeeping&amp;rsquo;, email notifications and so on. So, can be almost a case of set and forget (well set and monitor really).&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;When creating or maintaining a database, you can allocate disk space and can be easily controlled. &lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&lt;/span&gt;Consuming disk space can get a little more involved and is largely reactionary to the amount of activity. To help the DBA manage, there are the Database settings to help with sizing the database with Autoshrink and Autogrow. Immediately, without thinking, right now, disable Autoshrink. Having done that, you can then go and find out about Autoshrink and agree that turning it off is really the best thing to do. Autogrow is a bit different. When a database or log file is filling up the allocated space, it will decide at some point that it needs more disk. Autogrow sets the amount of disk that the database files will grow by. Given time, and maturity of the database, the size and growth rates will become more predictable, ideally to the point were the growth is fully managed and Autogrow is an exception.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;If you are seeing continual growth in the database files it could mean that you are either shrinking, or not managing the size. It could also be due to not running frequent enough transaction log backups. While Autogrow may happen, it really should be the exception and considered a safety measure to accommodate unpredicted activity. We don&amp;#39;t really want the overheads with the disk files to stop, grow, resume processing along with fragmentation that must surely result in trying to acquire additional disk. So, when using Autogrow, make it a reasonable amount so even if it must autogrow, the number of instances is minimal (or non-existant)&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;If you do set your database to simple recovery, the transaction log is managed for you. But then in the event of a database failure, your only protection is the last full backup, or last full backup and the last differential backup. For a typical OLTP type operation, SIMPLE is ill-advised. If your business depends on the information, then you will want high availability and high recoverability (meaning FULL recovery mode). A Read only database on the other hand like a data warehouse or reporting database probably does not need the same dynamic recoverability because they are typically batch updated (from the &amp;ldquo;real&amp;rdquo; transactions) and easy to schedule a full backup after the load, or recover from the original transactional database, so ideally suited to SIMPLE recovery model.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;So, if you do not already have them, and it is not the Express edition, then get those backups happening, and use the maintenance plans so it can be scheduled. In that regard, would suggest you create three new maintenance plans. &lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;1) Full backup - is a full backup run each day / night, or really, it depends on type and amount of activity. &lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;2) Transaction log backup - frequently during the day if running FULL recovery mode (otherwise do not worry about it). If not running FULL, you may consider Differential backups&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;3) Database Maintenance Tasks - run periodically to update statistics, rebuild indexes, manage / resize databases etc - normally run at a period where there are high volume turnovers such as an end of month purge / archive or similar - keeps database running efficiently &amp;ndash; could even run weekly over the weekend if you have some downtime available.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;So, what happens if we don&amp;#39;t ? that&amp;#39;s simple, you will have uncontrolled disk consumption and exposure to failure. So, what do I do if that hasn&amp;#39;t been done before ? that&amp;#39;s also simple, do it now - it is never too late. Or, what if I am running out of disk space already ? Then it is highly likely that you may have to shrink or resize the database files and keep it clean from that point forward.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;If you can, run a FULL backup and set up those maintenance plans. Maybe (big maybe) and only momentarily, change to SIMPLE recovery mode until you have your plans in place. This should not take long to set up and is done in SSMS. Changing to Simple, and then change back, do a FULL backup, will give you a &amp;ldquo;clean&amp;rdquo; log, but it will not be optimised for size and growth. Ideally you size your database files according to the maximum type of activity that will occur in the time frames / frequency dictated by your transaction log backups. That way, disk can be pre-allocated and then allowed to fill up that allocated space. These files can also autogrow, and so is not of &amp;ldquo;vital&amp;rdquo; importance, though, it is not desirable for all kinds of performance and fragmentation issues and ensuing IO performance impacts associated with frequent need to autogrow.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;If needed, using SSMS, you can also inspect and shrink your files by right clicking on the database, tasks, shrink, files and a window will popup. There is a drop down selection for looking at either the data file or the log file. The down the bottom, you can select some actions - best to use middle radio button to reorganise and also nominate some space. You do need to allow enough space for the data base to grow (physical allocation of disk, and then starts to use that space with data activity). The logs will typically shrink very quickly. The data files will take considerably longer. But you will only have success shrinking files if they can be truncated. That means you must release internal space before you can release (shrink) physical disk space.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;Now, we previously introduced the term truncation in terms of releasing space. Using Full Recovery, and regular transaction logs backups, the log files can be kept clean, but how does it do that ? SQL 2005 and 2008 rely on checkpoint processing after backups to truncate those logs :&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;Except when delayed for some reason, log truncation occurs automatically as follows:&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;1) Under the simple recovery model, after a checkpoint.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;2) Under the full recovery model or bulk-logged recovery model, after a log backup, if a checkpoint has occurred since the previous backup.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;A checkpoint is essential for truncating the log under the full recovery - there might still be other factors that prevent it from releasing space. If needed, explicitly invoke a checkpoint after the backup. &lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;You can check via:&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;select log_reuse_wait, log_reuse_wait_desc, * from sys.databases&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;-- looking for &amp;#39;checkpoint&amp;#39; in log_reuse_wait_desc.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;In FULL recovery, the inactive part of the log cannot be truncated until the log records have been captured in a transaction log backup. So, a moot point trying to shrink files without doing the backups, or releasing some of that internal space first.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;Having said all that above, heavily favouring the Full Recovery mode, we had one company in EE who decided on &amp;ldquo;ease of management&amp;rdquo;. Running a full backup of their Simple recovery database starting from 8:00am and then every two hours worked perfectly for them. Mind you it was not a huge database, and they processed a lot of parchments so recovery simply meant re-keying information. Really, they should have entertained the notion of differential backups, but it is the model that they chose and could cope with. It is quite a bit different if everything is electronic and you lose access to the source information.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;All this should be considered in line with your DR plan which most likely incorporates some wide reaching considerations. And believe it or not, with the higher reliability rates, there is less likelihood of failure, but, the more important the DR plan. Suffice it to say, you may need to restore your database at some point in time, for whatever reason (hardware failure, catastrophic failure, database corruption), and better to be in a position knowing that (if nothing else) the &amp;ldquo;Accidental DBA&amp;rdquo; has been able to save the database.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;There is a good article at : http://msdn.microsoft.com/en-us/library/ms178094(SQL.90).aspx &lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;And a colleague has written : &lt;a href="http://sqlservernation.com/blogs/admin/archive/2009/05/17/why-is-my-log-file-so-big.aspx" title="blocked::http://sqlservernation.com/blogs/admin/archive/2009/05/17/why-is-my-log-file-so-big.aspx"&gt;&lt;span style="color:#800080;"&gt;http://sqlservernation.com/blogs/admin/archive/2009/05/17/why-is-my-log-file-so-big.aspx&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;Hope you found this article of some benefit... And welcome to SQL Server.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://sqlservernation.com/aggbug.aspx?PostID=204" width="1" height="1"&gt;</content><author><name>mark_wills</name><uri>http://sqlservernation.com/members/mark_5F00_wills/default.aspx</uri></author><category term="Mark Wills" scheme="http://sqlservernation.com/blogs/admin/archive/tags/Mark+Wills/default.aspx" /><category term="Intermediate SQL" scheme="http://sqlservernation.com/blogs/admin/archive/tags/Intermediate+SQL/default.aspx" /></entry><entry><title>Managing Fragmentation for the Accidental DBA</title><link rel="alternate" type="text/html" href="/blogs/admin/archive/2009/05/28/managing-fragmentation-for-the-accidental-dba.aspx" /><id>/blogs/admin/archive/2009/05/28/managing-fragmentation-for-the-accidental-dba.aspx</id><published>2009-05-27T17:34:00Z</published><updated>2009-05-27T17:34:00Z</updated><content type="html">&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;by Mark Wills&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;We often here about Fragmentation, and generally have an idea that it is about broken bits, or bad for performance, or at least, is generally not a good thing. But what does it really mean ? &lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;By way of analogy, think of the humble Telephone Directory. It is nicely laid out, sequentially in alphabetical sequence by Name. Think about receiving the next edition, not by replacing the directory, but by giving you the added or altered pages which you append to the end. After a few updates, you will soon find that the end of the directory makes no sequential sense at all and you spend an inordinate amount of time trying to find that elusive phone number. It has become fragmented and your directories performance is most likely measured in terms of how long it takes before it hits the bin.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;With SQL Server systems there are two basic areas of fragmentation, Disk fragmentation dealing with physical files, and SQL Database fragmentation primarily dealing with how data is stored inside that physical file. There are a lot of parallels, and we will need to look at both.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;Disk fragmentation is more of a problem with the classic IO sub-system architectures, and much less of a problem on the more sophisticated IO system solutions such as SAN. Disk systems are made up of building blocks known as sectors, and collections of sectors known as clusters. When physical files occupy non-contiguous space, or, the growth of a physical file means that it needs to hunt down the next available sector, then it becomes fragmented.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;The big issue we often hear about within SQL is Index Fragmentation. But there is also Heap Fragmentation (ie tables without a clustered index or Primary Key) and potentially more of a problem. Those areas of fragmentation we see and discuss in SQL is really all about page management - everything SQL revolves around the humble 8K block known as a page, and groups of 8 of them known as extents - we will probably not get down to that level of detail, other than to be aware of the basic building blocks. Conceptually it is similar to Disk with pages and extents akin to sectors and clusters. Not surprisingly, the next few paragraphs, equally apply to Disk and to SQL fragmentation.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;Fragmentation, in all cases, is caused by one of two things. The first is the inability to provide sufficient contiguous space at that point in time when it is needed. The second is Data elements become segmented by occupying non-contiguous or fragmented space due to availability. This inability to provide contiguous space has the biggest impact on performance and in turn, causes two types of fragmentation, &amp;quot;external&amp;quot; and &amp;quot;data&amp;quot; fragmentation. &lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;quot;External&amp;quot; fragmentation occurs to the free or available space. We want it to be kept contiguously so that data can be written without being broken up into different locations. However, if data segments (such as a sector on disk or a page in SQL) are removed at arbitrary places, then the free space is automatically fragmented. In that case, defragmentation means shuffling all that free space (or moving occupied space) into contiguous segments, and conversely, making the available space nice and contiguous as well.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;quot;Data&amp;quot; fragmentation occurs as a result of external fragmentation, but can also occur within a contiguous allocation. It becomes fragmented as new data elements are written into available spaces, and contiguous blocks of information then contain pointers to the next physically available space. This will happen with volatile data, ie data that undergoes addition, changes, and deletions - such as a database.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;There is also &amp;quot;Internal&amp;quot; fragmentation. This occurs when a data element is unable to be stored in such a way that all available space is used to maximum efficiency. The only real impact in that situation is most likely wasted space more so than anything degenerative to performance. However, needing more space to occupy less data does have some impact on caching. An example and possible exception is the use of Fill Factor in SQL where you take control over the page &amp;quot;density&amp;quot; to accommodate inclusions, effectively reserving free space.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;Fragmentation can be further affected by the type of access to those data segments (regardless of Disk, Database, Indexes etc). Random access is largely independent on fragmented space, and actually leads towards fragmentation (ie small discrete blocks of data being independently read and/or written). Conversely, Sequential data is hugely dependant on contiguous space and is very much the victim of fragmentation. &lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;For SQL, there are tools to help with the statistics and to manage the various options, but it is of vital importance to learn about the dynamics of the business and the databases in use. For example, a periodically updated, largely &amp;quot;read only&amp;quot; databases like a data warehouse or reporting database will have different requirements on how you manage that database versus a considerably more random database such as a &amp;quot;typical&amp;quot; transactional database. Let&amp;#39;s consider our Telephone Directory again, but this time as a database. To use it on line, it becomes hugely random. To print a new book, it will be hugely sequential.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;Let us take a moment to reflect on what makes up a database. An SQL Database is made up of three types of file, the two main files are the primary data file with the extension of mdf and the transaction log file with the extension of ldf. The third is an optional secondary data file and has the extension ndf. As users add information into the database, it is stored in the data file. In turn, those transactions and database modifications can be recorded in the Transaction Log.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;Transaction Logs are sequential in nature (data continually added in a chronological sequence) whereas Data files are essentially random in nature (individual gets or puts from unrelated simultaneous concurrent users). So, from a physical perspective, the types of files in a database means that they are likely to be affected by fragmentation in different ways. Those differences in file types also influence the placement and sizing of those files onto a disk sub-system, even down to the type of RAID and caching methods being used. Kind of a catch-22 in some regards, but sitting, plotting and planning makes it all pretty mechanical at the disk level. &lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;The database files are simply large physical disk files and are built with an initial allocation of disk space. That means, you can reserve a pre-determined size for your database, and then set about filling it up. When creating or maintaining a database, your allocated disk space can be easily controlled, just a matter of knowing how big. Consuming that disk space can get a little more involved and is largely reactionary to the amount and type of activity. &lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;There are a couple of settings in the Database settings which are meant to help with sizing the database, but are potential catalysts for fragmentation. They are Autoshrink and Autogrow. Immediately, without thinking, right now, disable Autoshrink &#x13; enough said. Autogrow sets the amount of disk that the database files will grow by. When a database or log file is filling up the allocated space, it will decide at some point that it needs more disk and the database engine will grab the space as prescribed in the Autogrow settings. Given time, and maturity of the database, the size and growth rates will become more predictable, ideally to the point were the growth is fully managed and Autogrow is an exception. &lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;Unfortunately, &amp;quot;shrink database&amp;quot; or &amp;quot;grow database&amp;quot; operations are going to unravel and promote disk fragmentation by subsequently and dynamically changing our carefully planned size for the database, unless they are being very deliberately and very specifically performed. That is why we need to disable Autoshrink, and minimise Autogrow instances. If it does need to Autogrow, then you do need to make that incremental growth worthwhile to minimise the number of times the database is being extended. You can apply different growth factors to the individual database files.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;Fortunately, SQL gives us the one tool that has maximum impact to help combat Disk fragmentation by being able to allocate space in advance of its use. It is extremely important to do some homework and look at typical growth and then allocate the space required to accommodate normal / predicted growth that is for both the Data and the Log files that make up the Database. When first starting, you will need to determine (erring on the generous side) the amount of disk space that will be required, and monitor that usage so you can then determine the most appropriate size. &lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;For Databases, because they are simply big files, it is important to manage and resolve disk fragmentation before attempting any resolution of internal SQL fragmentation. Like any building, you need solid foundations before you contemplate furnishing the penthouse.&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;So, create your databases by carefully and deliberately sizing the physical files according to the nature and type of database and associated activity, even to the point of choosing a location (such as different disks and/or multi RAID systems) according to the underlying nature of the individual files of the database. Then once you have defragmented the disk, there will be good continuity of space available and resolves one hugely manageable aspect (and cause) of fragmentation. On that note we will leave Disk fragmentation alone.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;OK, we are now (finally) getting into the nitty gritty of SQL itself. &lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;First of all, need to understand that internal SQL fragmentation might not be as much of a problem as you may think, and vice versa, ie a database member maybe more fragmented than statistics might first suggest. If data is largely random, with optimised queries that can achieve a good hit ratio, then there is no real problem. Let&amp;#39;s revisit our Telephone Directory Database. For on-line, interactive use, it will be hugely random access and so, fragmentation is not necessarily a problem. To print a new book, it becomes sequential and fragmentation is potentially a huge problem. &lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;While still with our Telephone Directory, let us consider having received the first 2 pages of updates (appended to the end) showing a few new entries per alphabetic letter. Now, the few thousand pages (lets say 2000), is nicely structured, and the last 2 pages contains entries from all over the place. Using our tools, it may not be shown as fragmented (ie 1 page per thousand) but, in reality, doing a sequential scan, or an index rebuild will mean it shuffles nearly all the pages following the first instance of the letter &amp;quot;A&amp;quot; from the update pages, so it really is hugely and &amp;quot;logically&amp;quot; fragmented.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;So, while we can get all the statistics on fragmentation, it will be your business knowledge and the performance of various queries that will be the most likely indicators that fragmentation (within SQL) is causing a major problem. In our Telephone Directory, what if we were to only permit lookup and add of new phone numbers - the interaction is only random in nature, and fragmentation per se may not really be a problem, albeit present.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;At this stage we really do need to qualify some of those scenarios above. With SQL it is important to understand the difference between a table with a Clustered Index or Primary Key over ones that don&amp;#39;t. The former we will call an Indexed Table, and the latter is called a Heap table. An Indexed table provides a few benefits over a heap such as physically storing the data based on the clustered index, the ability to use the index to find the rows quickly and the ability to reorganize the data by rebuilding the clustered index. A heap table has no particular order of data, and must always refer back to the IAM (even for sequential access), and might have non-clustered indexes, otherwise random access is painful. Now, a clustered index has inherent pointer to row-data. Any subsequent indexes can use this pointer or key-value in their own indexes to point to the underlying data. Where is all this index structure is kept - on those basic building blocks called pages. Obviously the more compact and &amp;quot;dense&amp;quot; the index information is on a page, the more data can be pointed to, and similarly, the more contiguous pages the greater the caching in one extent, improving caching, and minimising the probability of swapping out one page for another.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;So, what leads to fragmentation ? It all depends on the INSERT, UPDATE and DELETE activity on your tables with your physical data and how it is distributed across the range of index keys. If only ever adding new chronologically correct data, then fragmentation is less likely to occur at the heap or data level - such as the transaction log. The real impact is non sequential activity, especially updates (particularly if updating columns which are also members of an index) and deletes (leaving &amp;quot;space&amp;quot; or wholes in otherwise contiguous data). Just as a side note that is one huge attraction with using surrogate keys such as identities or sequential GUID&amp;#39;s as primary keys and clustered indexes - they will be sequential and so reduce one big aspect of fragmentation.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;A query often used to identify fragmentation is :&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;SELECT object_name(s.object_id) as table_name,s.index_id, name, index_type_desc, avg_fragmentation_in_percent&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL, NULL, NULL) AS S&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;INNER JOIN sys.indexes AS i ON s.object_id = i.object_id AND s.index_id = i.index_id&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;ORDER BY 1,2&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;That DMV (Data Management View), despite its name, it not just indexes, and really it is a function, not just a view. It will show you a fragmentation percent, obviously higher the percent the more fragmented. But they are statistics and you need to apply your knowledge about the business to help ascertain the impact. There are a couple of other interesting DMVs for indexes that can be used in conjunction to help clarify how data is being accessed. The main one is sys.dm_db_index_operational_stats. That is beyond the scope of this article. It is worth noting that the DMVs and Alter Index statements are now the preferred SQL methods rather than the DBCC commands.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;Now, fixing fragmentation for indexes is pretty straight forward. Simply (?) rebuilding or reorganizing the index will fix the problem (more later). Heap is a lot more difficult to fix, but fixable if it has to be... Best possible solution is to simply create a clustered index on either an existing identity, or add an identity column as your clustered primary key, which if you really need to can be dropped afterwards. Otherwise, you will need to get into manipulating or managing the data as a bulk process by either exporting, truncating and re-importing, or copy to a new table and rename etc. Like I said, fixing fragmented heap space can be more difficult.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;But you really do need to ascertain not if there is fragmentation, but, if fragmentation is causing problems. You do need statistics on page life expectancy and buffer cache hit ratios as a starting point. Because an index rebuild on a large table can be a vey intense and time consuming exercise and really does need careful planning.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;So, what is rebuilding or reorganising an index. Well, we are told that the DBCC options are now deprecated and really need to use the newer functions like ALTER INDEX. The REBUILD is essentially recreating the index. If you are running the Enterprise Edition, you can also rebuild online using&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;WITH (ONLINE = {ON | OFF}), off=table is locked exclusively (the default), on=table can be shared, however, it uses more CPU and it generates a considerable number of locks. Someimes better to consider a REBUILD as being an exclusive task. When rebuilding, you do need to start with clustered indexes, or, use the ALL option rather than specify each index name. REORGANIZE does not require exclusive locks as it is more simply reorganizing the leaf nodes of the index, and so, can be run online.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;ALTER INDEX {&amp;lt;index name&amp;gt; | ALL} ON &amp;lt;table name&amp;gt; {REBUILD | REORGANIZE}&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;According to Books On Line, it is recommended that we consider rebuild when fragmentation if 30% or greater. In reality that is a very conservative number, and a more general consensus is indexes should be rebuilt when fragmentation is greater than 40%. So, that would mean indexes should be reorganized when fragmentation is less than 40%. In reality, I prefer the 80/20 rule. You will need to do something if fragmentation is above 20%. If is under 20%, then reorganize is the most likely option but only if you see performance being impaired. &lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;Anyway whatever threshold you choose, and it may be different depending on individual tables, fixing fragmentation is an orchestrated set of events, and can (ideally) be automated, at least for the SQL parts... &lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;1) Set optimal database size allocations (and locations) by file, do not shrink unless really needed, defrag disk once size has been set (or changed). Look at realistic autogrowth settings.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;2) Run SQL backups - Run transaction log backup frequently to help reduce growth factors and release internal space within the transaction log disk allocation.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;3) Keep &amp;quot;external&amp;quot; fragmentation down. Reorganise your database moving used pages to the front, releasing unused pages at the end.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;4) Use statistics to help identify internal fragmentation and use REBUILD or REORGANIZE. Start with Clustered indexes first, then move on to non-clustered. &lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;5) It can be more efficient to drop indexes and recreate. Beware of any check constraints and foreign keys.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;6) Ascertain the thresholds where rebuild is required over reorganise.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;7) Set up Maintenance plans to do all the above and have them run frequently enough to manage any possible fragmentation.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;8) If you have a convenient time window (such as &amp;quot;we do not normally work on the weekend&amp;quot;), then use that time and only that time to do any rebuilding and reorganizing.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;9) If you have periodic processes such as an end of month purge or archive, then schedule this type of activity via maintenance plans to follow the periodic processes. &lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;The last point above is probably the most important to consider. Really what you want to do is to set up an automated maintenance task to run in a time window where you can look at restructures in accordance with business activity and processes (such as end of month purges / archiving historical data). Take snapshots of information - that is where you can gain a lot of insight into your business activity impact on a database. &lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;You can then use and modify those maintenance plans to fix disk allocation, alert disk fragmentation, reorganise pages, rebuild indexes, update statistics in that sequence. After all that has been said, you might not need to fix every reported case of fragmentation, but if you have the window of opportunity, then you can also pretty much eradicate fragmentation from your database to the point where fragmentation is always being proactively managed.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:9pt;font-family:Verdana;mso-bidi-font-family:Arial;" lang="EN-AU"&gt;Hope you found this article useful...&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://sqlservernation.com/aggbug.aspx?PostID=203" width="1" height="1"&gt;</content><author><name>mark_wills</name><uri>http://sqlservernation.com/members/mark_5F00_wills/default.aspx</uri></author><category term="Mark Wills" scheme="http://sqlservernation.com/blogs/admin/archive/tags/Mark+Wills/default.aspx" /><category term="Intermediate SQL" scheme="http://sqlservernation.com/blogs/admin/archive/tags/Intermediate+SQL/default.aspx" /></entry><entry><title>Why is my Log File So Big?</title><link rel="alternate" type="text/html" href="/blogs/admin/archive/2009/05/17/why-is-my-log-file-so-big.aspx" /><id>/blogs/admin/archive/2009/05/17/why-is-my-log-file-so-big.aspx</id><published>2009-05-17T15:46:00Z</published><updated>2009-05-17T15:46:00Z</updated><content type="html">&lt;p&gt;So, you&amp;#39;ve ran into a problem.&amp;nbsp; Everything has been running smoothly on your SQL Server database until recently.&amp;nbsp; You have noticed that your drives are out of space, or when you&amp;#39;re browsing the files on your system that the log files (typically with an extension of .ldf) are HUGE...as big as or bigger than your data files.&amp;nbsp; This, of course, doesn&amp;#39;t make sense to you since you&amp;#39;re doing nighly backups and everything until lately seems to have been working properly.&amp;nbsp; So, what could be the issue?&lt;/p&gt;
&lt;p&gt;This is a VERY common issue in the SQL Server world, and typically has a small set of factors that contribute to the &amp;quot;problem&amp;quot;, and they&amp;#39;re all relatively easy to solve.&amp;nbsp; But, before we can solve the problem, we need do discuss a little bit as to what causes it.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;The issue almost certainly stems from the fact that your database is set to the FULL recovery model, which is the SQL Server default for new databases.&amp;nbsp; The other option is that you have a long running transactions and the inactive portion of the log cannot be truncated or that you&amp;#39;re using transactional replication or database mirroring and the transactions hasn&amp;#39;t been replicated yet.&amp;nbsp; For sake of simplicity, I&amp;#39;ll omit&amp;nbsp;these scenarios&amp;nbsp;for this article.&lt;/p&gt;
&lt;p&gt;When a transaction occurs, such as an UPDATE to a table, the transaction is first committed to the log file.&amp;nbsp; At this point the transaction is considered committed to the database.&amp;nbsp;&amp;nbsp;At some later point in time, the CHECKPOINT process will commit the changes to data pages on disk.&amp;nbsp; Once the CHECKPOINT process does this, these transactions are now essentially inactive because they&amp;#39;ve been committed.&amp;nbsp; If your database is in the FULL recovery (or BULK logged for that matter) model, these inactive transactions will stay inside your log file (.ldf) until you do something to clean them up.&amp;nbsp; Performing a FULL or DIFFERNTIAL backup does nothing to remove these inactive tranactions.&amp;nbsp;&amp;nbsp;Removing these inactive transactions can be done basically two different ways.&amp;nbsp; First, performing regular transaction log backups will remove these inactive transactions and place them in the backup file.&amp;nbsp; This is the recommended, and basically only safe way to remove these inactive transactions.&amp;nbsp; The other way, which should be avoided at almost all costs, is to truncate these inactive records by hand.&amp;nbsp; I&amp;#39;ll not show you how to do this in this writing because doing so breaks your log chain, which makes it impossible to recovery to a point in time (which is really the reason for using the FULL recovery model).&amp;nbsp; If you&amp;#39;ve found that you&amp;#39;re out of space, and truncation is the only option to get you up and running again, &lt;a href="http://blogs.techrepublic.com.com/datacenter/?p=448" title="Log File Too Full"&gt;see this article I wrote&lt;/a&gt; that mentions a way to do it.&lt;/p&gt;
&lt;p&gt;If you find yourself continually having log problems, there are two steps you can take to remedy your situation. &lt;/p&gt;
&lt;p&gt;1.&amp;nbsp; Start taking regular log backups.&amp;nbsp; You can adjust your Maintenance Plan to include these log backups, or adjust your backup scripts to do so also.&amp;nbsp; This is the ideal change to make as doing so will allow you to recover your database to a previous state at a point in time before any type of disaster that may occur.&amp;nbsp; As you can imagine, having the ability to do may save your (and your company&amp;#39;s) neck someday.&lt;/p&gt;
&lt;p&gt;2.&amp;nbsp; Change your recovery mode to Simple.&amp;nbsp; If you&amp;#39;re not doing log backups and do not plan to in the future, there is really no advantage for you to have your database in the FULL recovery mode.&amp;nbsp; The difference between the two is that in the SIMPLE recovery mode, the inactive portion of the log is truncated for you automatically.&amp;nbsp; However, you&amp;#39;ll never be able to recovery to a point in time using this recovery mode...which is fine if your situation does not warrant being able to do so.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Shrinking The Log&lt;br /&gt;&lt;/strong&gt;You&amp;#39;ll notice that once you do a log backup by hand, or you do a manual truncation of the log, the size of the file has not changed.&amp;nbsp; This is at first somewhat confusing considering you have likely just removed a large number of inactive transaction log records.&amp;nbsp; These inactive records have been removed but SQL Server will not allow the operating system to reclaim this space.&amp;nbsp; To do so, you can use a shrink command to&amp;nbsp;free the space.&amp;nbsp; This is generally not a good idea to do on a continual basis as it can lead to performance issues.&amp;nbsp; The good thing is that if you&amp;#39;re doing frequent enough log backups (or your recovery mode is set to SIMPLE), the space of the log file should not become a problem.&lt;/p&gt;
&lt;p&gt;Here is how you can shrink your log file if you really need to:&lt;/p&gt;
&lt;p&gt;DBCC SHRINKFILE(&amp;#39;DatabaseName_Log&amp;#39;, 0)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Conclcusion&lt;/strong&gt;&lt;br /&gt;I hope todays discussion of how transaction log backups work and how you can use them to your advantage.&amp;nbsp; If you have further questions, feel free to post a question in our forums.&amp;nbsp; We would be happy to help you with any log problems you may have.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://sqlservernation.com/aggbug.aspx?PostID=197" width="1" height="1"&gt;</content><author><name>TimChapman</name><uri>http://sqlservernation.com/members/TimChapman/default.aspx</uri></author><category term="Intermediate SQL" scheme="http://sqlservernation.com/blogs/admin/archive/tags/Intermediate+SQL/default.aspx" /><category term="Transaction Log" scheme="http://sqlservernation.com/blogs/admin/archive/tags/Transaction+Log/default.aspx" /></entry><entry><title>Enable and Disable Batches of SQL Agent Jobs</title><link rel="alternate" type="text/html" href="/blogs/admin/archive/2009/04/13/enable-and-disable-batches-of-sql-agent-jobs.aspx" /><id>/blogs/admin/archive/2009/04/13/enable-and-disable-batches-of-sql-agent-jobs.aspx</id><published>2009-04-13T19:13:00Z</published><updated>2009-04-13T19:13:00Z</updated><content type="html">&lt;p&gt;In the following system stored procedure I allow a list of SQL Server Agent job names to be passed as an XML document.&amp;nbsp; The procedure accepts the list of Job names, parses them out, and will enable or disable them based on the @enabled parameter passed into the procedure.&amp;nbsp; This procedure is VERY handy for those situations where you need to disable a batch of jobs, and then enable them later on.&amp;nbsp; It saves you from having to remember which jobs you disabled, along with saving you from having to go into SQL Server Management Studio to enable the jobs one by one.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Note:&amp;nbsp; The technique I use to parse the XML in this stored procedure is applicable to SQL Server versions 2005 and later.&lt;/p&gt;
&lt;pre style="font-size:12px;overflow:auto;width:100%;color:#000000;line-height:14px;font-family:Andale Mono, Lucida Console, Monaco, fixed, monospace;background-color:#eee;border:#999999 1px dashed;padding:5px;"&gt;&lt;code&gt;USE [master]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
/*********************************************************************************************
*  Author:  Tim Chapman
***********************************************************************************************/
CREATE PROCEDURE [dbo].[sp_EnableJobList]
(
    @xml XML,
    @enabled TINYINT
)
AS
BEGIN

    DECLARE  tempcursor
    CURSOR
    READ_ONLY
    FOR 

    SELECT name 
    FROM msdb..sysjobs
    WHERE name IN
        (
            SELECT t.c.value(&amp;#39;@name&amp;#39;, &amp;#39;varchar(30)&amp;#39;)
            FROM @xml.nodes(&amp;#39;/jobs/job&amp;#39;) t(c)
        )

    DECLARE @name SYSNAME
    OPEN tempcursor

    FETCH NEXT FROM tempcursor INTO @name
    WHILE (@@fetch_status &amp;lt;&amp;gt; -1)
    BEGIN
            EXECUTE msdb..sp_Update_Job
            @job_name = @name,
            @enabled = @enabled

            PRINT &amp;#39;JOB: &amp;#39; + @name + &amp;#39; has been &amp;#39; + CASE @enabled WHEN 0 THEN &amp;#39;Disabled.&amp;#39; ELSE &amp;#39;Enabled.&amp;#39; END

        FETCH NEXT FROM tempcursor INTO @name
    END

    CLOSE tempcursor
    DEALLOCATE tempcursor
END
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;Here&amp;#39;s how you can call the above stored procedure to disable or enable a batch of jobs.&amp;nbsp; In this scenario, I am disabling 3 jobs; Job1, Job2, and Job3.&amp;nbsp; I can just as easily enable them by flipping the @enabled parameter to 1 and run the procedure again.&lt;/p&gt;
&lt;pre style="font-size:12px;overflow:auto;width:100%;color:#000000;line-height:14px;font-family:Andale Mono, Lucida Console, Monaco, fixed, monospace;background-color:#eee;border:#999999 1px dashed;padding:5px;"&gt;&lt;code&gt;DECLARE @xml XML
SET @xml = &amp;#39;
    &amp;lt;jobs&amp;gt;
    &amp;lt;job name = &amp;quot;Job1&amp;quot;/&amp;gt;
    &amp;lt;job name = &amp;quot;Job2&amp;quot;/&amp;gt;
    &amp;lt;job name = &amp;quot;Job3&amp;quot;/&amp;gt;
    &amp;lt;/jobs&amp;gt;&amp;#39;

EXECUTE [sp_EnableJobList]
@xml = @xml,
@enabled = 0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you might imagine, using an XML document to send in a list of parameters to a stored procedure has a powerful effect.&amp;nbsp; In this scenario, I am taking a list of jobs and enabling or disabling them.&amp;nbsp; If you play around with the concept, you&amp;#39;ll see that there are hunderes of scenarios that this same technique can be appleid to.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://sqlservernation.com/aggbug.aspx?PostID=158" width="1" height="1"&gt;</content><author><name>TimChapman</name><uri>http://sqlservernation.com/members/TimChapman/default.aspx</uri></author><category term="Intermediate SQL" scheme="http://sqlservernation.com/blogs/admin/archive/tags/Intermediate+SQL/default.aspx" /><category term="Beginner SQL" scheme="http://sqlservernation.com/blogs/admin/archive/tags/Beginner+SQL/default.aspx" /></entry><entry><title>Getting Table Row Counts</title><link rel="alternate" type="text/html" href="/blogs/admin/archive/2009/04/13/getting-table-row-counts.aspx" /><id>/blogs/admin/archive/2009/04/13/getting-table-row-counts.aspx</id><published>2009-04-13T18:48:00Z</published><updated>2009-04-13T18:48:00Z</updated><content type="html">&lt;p&gt;Here&amp;#39;s a quick and easy script you can use in SQL Server 2005 to return the number of rows in a table, along with the index size on the table, the reserved space, and the data space for the table.&amp;nbsp; If you&amp;#39;re familiar with the system stored procedure sp_spaceused, this information may seem familiar to you.&amp;nbsp; I took some of this code from that procedure, but am presenting it in such a way so that it works for all tables in the database at the same time.&amp;nbsp; This makes it much easier to query, and the values returned are not in a variable character format.&lt;/p&gt;
&lt;pre style="font-size:12px;overflow:auto;width:100%;color:#000000;line-height:14px;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;background-color:#eeeeee;border:#999999 1px dashed;padding:5px;"&gt;&lt;code&gt;SELECT
  TableName = OBJECT_NAME(id),
  NumberOfRows = CONVERT (CHAR(11), TheRowCount),
  Reserved_KB = ReservedPages * 8,
  Data_KB = Pages * 8,
  IndexSize_KB = CASE WHEN UsedPages &amp;gt; Pages THEN (UsedPages - Pages)
                       ELSE 0
                  END * 8,
  Unused_KB = CASE WHEN ReservedPages &amp;gt; UsedPages
                   THEN (ReservedPages - UsedPages)
                   ELSE 0
              END * 8,
  SchemaName = s.name
FROM
  (
   SELECT
        id = object_id,
        ReservedPages = SUM(reserved_page_count),
        UsedPages = SUM(used_page_count),
        Pages = SUM(CASE WHEN (index_id &amp;lt; 2)
                         THEN (in_row_data_page_count
                               + lob_used_page_count
                               + row_overflow_used_page_count)
                         ELSE lob_used_page_count
                              + row_overflow_used_page_count
                    END),
        TheRowCount = SUM(CASE WHEN (index_id &amp;lt; 2) THEN row_count
                               ELSE 0
                          END)
   FROM
        sys.dm_db_partition_stats p
   GROUP BY
        objecT_id
  ) a
  JOIN sys.objects o ON a.id = o.object_id
  JOIN sys.schemas s ON o.schema_id = s.schema_id
WHERE
  s.name = &amp;#39;dbo&amp;#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://sqlservernation.com/aggbug.aspx?PostID=156" width="1" height="1"&gt;</content><author><name>TimChapman</name><uri>http://sqlservernation.com/members/TimChapman/default.aspx</uri></author><category term="Intermediate SQL" scheme="http://sqlservernation.com/blogs/admin/archive/tags/Intermediate+SQL/default.aspx" /><category term="Beginner SQL" scheme="http://sqlservernation.com/blogs/admin/archive/tags/Beginner+SQL/default.aspx" /></entry><entry><title>How to easily DROP and CREATE foreign key constraints</title><link rel="alternate" type="text/html" href="/blogs/admin/archive/2009/03/24/how-to-disable-and-enable-foreign-keys.aspx" /><id>/blogs/admin/archive/2009/03/24/how-to-disable-and-enable-foreign-keys.aspx</id><published>2009-03-24T18:56:00Z</published><updated>2009-03-24T18:56:00Z</updated><content type="html">&lt;p&gt;&amp;nbsp;Here&amp;#39;s a helpful bit of code I use a lot to generate the statements to DROP and CREATE all of the foreign key constraints on a database.&amp;nbsp; This is useful for going through and using TRUNCATE on tables that would normally not allow truncation due to the foreign key constraints defined.&amp;nbsp; &lt;/p&gt;
&lt;pre style="font-size:12px;overflow:auto;width:100%;color:#000000;line-height:14px;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;background-color:#eeeeee;border:#999999 1px dashed;padding:5px;"&gt;&lt;code&gt;USE [master]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

/*********************************************************************************************
Copyright SQLServerNation.com
*  Author:  Tim Chapman
***********************************************************************************************/
CREATE PROCEDURE [dbo].[sp_ShowForeignKeyObjects]
AS
    SELECT 
        OBJECT_NAME(constid) AS ConstraintName,
        OBJECT_NAME(fkeyid) + &amp;#39;.&amp;#39; + COL_NAME(fkeyid, fkey) AS ForeignKeyObject,
        OBJECT_NAME(rkeyid) + &amp;#39;.&amp;#39; + COL_NAME(rkeyid, rkey) AS ReferenceKeyObject, 
        COL_NAME(fkeyid, fkey) AS ForeignKeyColumn,
        COL_NAME(rkeyid, rkey) AS ReferenceKeyColumn, 
        constid AS ConstraintID, 
        OBJECT_NAME(fkeyid) AS ForeignKeyTable,         
        fkeyid AS ForeignKeyID, 
        OBJECT_NAME(rkeyid) AS ReferenceKeyTable,
        rkeyid AS ReferenceKeyID,
        keyno AS KeySequenceNumber
    FROM 
        sysforeignkeys
    ORDER BY 
        OBJECT_NAME(rkeyid) ASC, COL_NAME(rkeyid, rkey)

GO
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;Now that I have my helper function defined, I can define a system procedure in the master database to generate the&amp;nbsp;TSQL statements to disable all foreign key constrains and also the TSQL to enable them.&amp;nbsp; This script makes use of the helper procedure I just defined and generates the script to drop all foreign keys on your system and adjoining script to recreate them.&amp;nbsp; &lt;/p&gt;
&lt;pre style="font-size:12px;overflow:auto;width:100%;color:#000000;line-height:14px;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;background-color:#eeeeee;border:#999999 1px dashed;padding:5px;"&gt;&lt;code&gt;
IF OBJECT_ID(&amp;#39;tempdb..#FK&amp;#39;)&amp;gt;0
	DROP TABLE #FK

IF OBJECT_ID(&amp;#39;tempdb..#Const&amp;#39;)&amp;gt;0
	DROP TABLE #Const

CREATE TABLE #FK
(
	ConstraintName VARCHAR(255),
	ForeignKeyObject VARCHAR(255),
	ReferenceObject VARCHAR(255),
	ForeignKeyColumn VARCHAR(255),
	ReferenceKeyColumn VARCHAR(255),
	ConstraintID INT, 
	ForeignKeyTable VARCHAR(255),
	ForeignKeyID INT, 
	ReferenceKeyTable VARCHAR(255),
	ReferenceKeyID INT, 
	KeySequenceNumber SMALLINT
)

CREATE TABLE #Const
(
	ConstraintID INT, 
	FBuildField VARCHAR(2000) DEFAULT(&amp;#39;&amp;#39;), 
	RBuildField VARCHAR(2000) DEFAULT(&amp;#39;&amp;#39;), 
	CountField SMALLINT 
)

INSERT INTO #FK
EXEC sp_Showforeignkeyobjects

SET NOCOUNT ON
DECLARE  tempcursor
CURSOR
READ_ONLY
FOR 

	SELECT 	
		f.ConstraintName ,
		f.ForeignKeyObject ,
		f.ReferenceObject ,
		f.ForeignKeyColumn ,
		f.ReferenceKeyColumn,
		f.ConstraintID , 
		f.ForeignKeyID , 
		f.ReferenceKeyID , 
		f.KeySequenceNumber, 
		f.ForeignKeyTable,
		f.ReferenceKeyTable 
	FROM #FK AS  f
		INNER JOIN 
		(
			SELECT ConstraintID, MAX(KeySequenceNumber) AS MaxSeq
			FROM #FK AS  k
			GROUP BY k.ConstraintID
		)b ON f.ConstraintID = b.ConstraintID AND f.KeySequenceNumber = b.MaxSeq

DECLARE 
	@ConstraintName VARCHAR(255),
	@ForeignKeyObject VARCHAR(255),
	@ReferenceObject VARCHAR(255),
	@ForeignKeyColumn VARCHAR(255),
	@ReferenceKeyColumn VARCHAR(255),
	@ConstraintID INT, 
	@ForeignKeyID INT, 
	@ReferenceKeyID INT, 
	@KeySequenceNumber SMALLINT, 
	@ForeignKeyTable VARCHAR(255),
	@ReferenceKeyTable VARCHAR(255)

OPEN tempcursor

	FETCH NEXT FROM tempCursor INTO 
	@ConstraintName ,
	@ForeignKeyObject ,
	@ReferenceObject ,
	@ForeignKeyColumn ,
	@ReferenceKeyColumn,
	@ConstraintID , 
	@ForeignKeyID , 
	@ReferenceKeyID, 
	@KeySequenceNumber,
	@ForeignKeyTable ,
	@ReferenceKeyTable 

WHILE (@@fetch_status &amp;lt;&amp;gt; -1)
BEGIN

	DECLARE  tempcursor2
	CURSOR
	READ_ONLY
	FOR 
	
		SELECT ConstraintID, ForeignKeyColumn, ReferenceKeyColumn, KeySequenceNumber 
		FROM #FK 
		WHERE ConstraintID = @ConstraintID

		ORDER BY ConstraintID, KeySequenceNumber ASC
	
	DECLARE @ConstraintID2 INT, @ForeignKeyColumn2 VARCHAR(255), @ReferenceKeyColumn2 VARCHAR(255), @KeySequenceNumber2 SMALLINT
	DECLARE @FKeyBuildField VARCHAR(1000), @RKeyBuildField VARCHAR(1000), @Cnt SMALLINT 
	
	OPEN tempcursor2

	SELECT @FKeyBuildField = &amp;#39;&amp;#39;, @RKeyBuildField = &amp;#39;&amp;#39;, @Cnt = 0

	FETCH NEXT FROM tempcursor2 INTO @ConstraintID2 , @ForeignKeyColumn2 , @ReferenceKeyColumn2 , @KeySequenceNumber2
	WHILE (@@fetch_status &amp;lt;&amp;gt; -1)
	BEGIN
		SET @Cnt = @Cnt + 1
		SELECT @FKeyBuildField = @FKeyBuildField  + ISNULL(@ForeignKeyColumn2,&amp;#39;&amp;#39;)+ 
			CASE 
				WHEN @ForeignKeyColumn2 IS NULL THEN &amp;#39;&amp;#39; 
			ELSE  
				CASE WHEN @KeySequenceNumber = @KeySequenceNumber2 THEN &amp;#39;&amp;#39; ELSE &amp;#39;,&amp;#39; END
			END

		SELECT @RKeyBuildField = @RKeyBuildField  + ISNULL(@ReferenceKeyColumn2,&amp;#39;&amp;#39;)+ 
			CASE 
				WHEN @ReferenceKeyColumn2 IS NULL THEN &amp;#39;&amp;#39; 
			ELSE  
				CASE WHEN @KeySequenceNumber = @KeySequenceNumber2 THEN &amp;#39;&amp;#39; ELSE &amp;#39;,&amp;#39; END
			END
	
		INSERT INTO #Const
		(	
			ConstraintID , 
			FBuildField , 
			RBuildField, 
			CountField  
		)
		VALUES
		(
			@ConstraintID, 
			@FKeyBuildField,
			@RKeyBuildField,
			@Cnt
		)

		FETCH NEXT FROM tempcursor2 INTO @ConstraintID2 , @ForeignKeyColumn2 , @ReferenceKeyColumn2 , @KeySequenceNumber2
	END
	CLOSE tempcursor2
	DEALLOCATE tempcursor2

	FETCH NEXT FROM tempCursor INTO 
	@ConstraintName ,
	@ForeignKeyObject ,
	@ReferenceObject ,
	@ForeignKeyColumn ,
	@ReferenceKeyColumn,
	@ConstraintID , 
	@ForeignKeyID , 
	@ReferenceKeyID , 
	@KeySequenceNumber ,
	@ForeignKeyTable ,
	@ReferenceKeyTable 
END

CLOSE tempcursor
DEALLOCATE tempcursor

SELECT &amp;#39;ALTER TABLE [&amp;#39; + FKTable + &amp;#39;] DROP CONSTRAINT &amp;#39; + OBJECT_NAME(a.ConstraintID) AS DropKeys,
&amp;#39;ALTER TABLE [&amp;#39; + FKTable + &amp;#39;] WITH NOCHECK ADD CONSTRAINT &amp;#39; + OBJECT_NAME(a.ConstraintID) + &amp;#39; FOREIGN KEY(&amp;#39; + FBuildField + &amp;#39;) REFERENCES &amp;#39; + RKTable + &amp;#39;(&amp;#39; + RBuildField+&amp;#39;)&amp;#39; AS BuildKeys
,*
FROM #Const a
JOIN
(
	SELECT ConstraintID, MAX(countfield) AS maxcount
	FROM #Const
	GROUP BY ConstraintID
) b ON a.ConstraintID = b.ConstraintID  AND a.countfield = b.maxcount
JOIN
(
SELECT DISTINCT constraintid, OBJECT_NAME(foreignkeyid) AS FKTable, OBJECT_NAME(referencekeyid) AS RKTable FROM #fk
) c ON a.constraintid = c.constraintid

DROP TABLE #Const
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;Once you generate the DROP and CREATE scripts, save them to a file somewhere.&amp;nbsp; You copy all of the DROP scripts and run them now, but make sure you have the CREATE script saved somewhere.&amp;nbsp; You&amp;#39;ll need to run it later once you&amp;#39;ve went through truncated your tables.&amp;nbsp; &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://sqlservernation.com/aggbug.aspx?PostID=157" width="1" height="1"&gt;</content><author><name>TimChapman</name><uri>http://sqlservernation.com/members/TimChapman/default.aspx</uri></author><category term="Intermediate SQL" scheme="http://sqlservernation.com/blogs/admin/archive/tags/Intermediate+SQL/default.aspx" /><category term="Beginner SQL" scheme="http://sqlservernation.com/blogs/admin/archive/tags/Beginner+SQL/default.aspx" /></entry></feed>