SQL Server Database Growth and Autogrowth Settings

SQL Server Database Growth and Autogrowth Settings

It's easy to create a database nowadays with point-'n-click, but if you've left your database's autogrowth settings at their default, you may hit problems in the future. Why? What do I do about it? Read on!
There are a lot of maintenance jobs that SQL Server performs under the covers. Whilst this makes SQL Server an easier database management system to administer with very little training, it has the consequence that the industry has many accidental DBAs who are managing SQL Server without really knowing what the database engine does behind the scene to keep their databases up and running. Microsoft provides point and click actions to define a number of maintenance tasks like defining databases, creating tables, backing up databases, performing data integrity checks, shrinking databases, etc. Being able to create these routine database administration tasks provides using point and click provides the accidental DBA an easy method to quickly build maintenance routines.
Many of these automatic maintenance events that SQL Server handles for you are controlled using configurable settings that have predetermined values which might not be appropriate in all installations. As a DBA you have control to override the predetermined configuration settings and you should consider providing a setting that is appropriate for your situation, One of those settings you should know something about is the ‘auto-growth’ settings that are established when you first create a database. In this article I will discuss the auto-growth options for a database, and how you should use it to appropriately manage your database growth. Additionally, I will provide you with some scripts to help you manage your database auto-growth events.

Auto-growth

What exactly are auto-growth events? An auto-growth event is the process by which the SQL Server engine expands the size of a database file when it runs out of space. The amount by which a database file grows is based on the settings that you have for the file growth options for your database.
Each database file that is associated with your database has an auto-growth setting. There are three different settings you can use to identify how your database files will grow. They can grow by a specific size, a percentage of the current size, or not grow at all. Additionally you can set your files to unrestricted growth, which means they will keep growing as they need more space or you run out of disk space. Or you can restrict the growth of a database file to grow no larger than a specified size. Each one of these different auto-grow setting have defaults, or you can set them for each database file.
If you are not properly managing your auto-growth setting for a database, then your database might experience many auto-grow events, or very few. Auto-growth events. Each time an auto-growth event is performed SQL Server holds up database processing while an auto-growth event occurs. This means that processing against that database will be held up while the auto-growth event completed. This equates to slower response time for those SQL commands that are being processing against the database that is growing.
When an auto-growth event occurs SQL Server needs to find additional disk space in which the database can grow. Most likely this disk space will not be physically right next to the existing database space, but instead will be somewhere else on the disk. This causes your database file to be physically fragmented on the disk. The more auto-growth events you have the more physical fragmentation you will have. When your database is physically fragmented it takes longer for SQL Server to read that databases, because it has to move the disk head around to all the different fragmented pieces to read your database. To avoid the issues associated with auto-growth events you need to minimize the number of auto-growth events that occur.
The default auto-growth settings for a database are rarely the ideal settings for how your database should grow. If you have an idea of the growth profile of your database when you first build it then you should set your auto-growth properties based on those growth projections. If you don’t have any idea of how fast your database will grow then you should be monitoring for auto-growth events. Knowing how often your database grows will give you some ideas of the growth rate of your database.

Establishing Your Auto-growth Settings When Creating a New Database

You can set database auto-growth setting by using SQL Server Management Studio, scripted SMO or by using T-SQL when you create your database. You can also use these methods to change the auto-growth settings of existing databases. Let me first show you how to set the auto-grow settings using SQL Server Management Studio when you create a database.
The initial settings for auto-growth are set to the default values when defining a new database. These defaults are established by using the auto-growth settings on the model database files. You can see my default values on the “New Database” screen shot in Figure 1 when I am creating a new database named “MyDB”. My default auto-growth setting for the data file is 1 MB with unrestrictive growth, and the log file is set to grow by 10% with unrestricted growth. If you haven’t tweaked your model database settings then you will have the same default auto-growth setting as I do.
1395-image001small.png
Figure 1: Setting Auto-grow settings using the New Database dialog
By clicking on the ellipses buttons, which are circled in red in Figure 1, I can define auto-growth settings that make sense for the database I am creating. When I click on the ellipses button the Windows dialog box in Figure 2 is displayed.
1395-image002.png
Figure 2: Options for Changing the Autogrowth settings
Using the dialog box shown in Figure 2 I can change my file auto-growth option to any one of the three different possible values. The first option is the check box at the top that says “Enable Autogrowth”. This option allows you to turn on or off whether “MyDB” can auto-grow. By having this box checked I’m telling SQL Server to allow this database to auto-grow. By unchecking this box I’m telling SQL Server I do not want my database to auto-grow.
The next option I can set is the “File Growth” option. It allows me to set how my data file will grow when it runs out of space. As you can see there are two radio buttons identifying whether or not you want the file to grow by a percentage or in megabytes. I normally only allow my database auto-grow settings to grow based on megabytes instead of a percentage; I do this because I want all my auto-growth events to be of a uniform fixed size. If I was to allow them to grow based on a percentage, the auto-growth amount would get bigger as my database got larger. When databases are allowed to grow by a percentage the amount they grow might be substantial especially for the large multi-gigabyte or terabyte databases. If a large database was to grow based on a percentage it most likely will take way more space then it will needs to handle growth for next year, or so. This causes these large databases to be over allocated from a disk space perspective. Worse yet a large database might grow so big it takes all the available disk space, and we don’t want this to happen. When setting the number of megabytes a new database should grow I do it based on whatever information I have regarding the growth profile of the new database.
The last option is the “Maximum File Size” option. This option allows me to set the maximum size that SQL Server will allow my file to grow. I normally use the unrestricted growth option, because I know most of my applications are well behaved and are highly unlikely to grow uncontrollably. Plus using the unrestricted options minimizes application failures due to auto-growth restrictions. I also monitor disk space usage and auto-growth events fairly close so I would most likely notice a database consuming all of my available disk space. If you want to make sure no one database uses up all your disk space then setting a maximum file size would be a way to prevent this.
If you are using T-SQL to create a new database you can set the auto-growth options on the CREATE DATABASE command. The code in Listing 1 shows how I can set auto-growth option when I create a new database named AnotherDB.
Listing 1: Setting auto-grow sizes when creating database using T-SQL
If you look at the code in Listing 1 you can see that I used the MAXSIZE, and FILEGROWTH options of the CREATE DATABASE command to control the auto-growth options of my database files. The MAXSIZE option is used to specify how large a file can grow and the FILEGROWTH option is used to specify how much my file is supposed to grow each time it needs to grow. The code in Listing 1 allows my file “AnotherDB_data” to grow to a maximum size of 500MB in 25MB chunks. For the log file “AnotherDB_log”, I allowed it to grow unrestricted, since I didn’t provide a “MAXSIZE” options, but when it does grow it will grow in “5MB” chunks.

Identifying Databases that are using the Default Auto-growth Settings

The default auto-grow settings associated with the installed model database are not the best settings for how databases grows. If you have inherited a SQL Server Instance, or haven’t been diligent at setting the auto-grow parameters when you created databases then you might want scan your instance to determine which databases are using the default setting.
Remember now that the default settings for auto-growing for the model database that is installed with SQL Server data is 1 MB for data files and 10% for log files. Therefore it is a simple matter of running a T-SQL script against your instance to identify those databases that are using the default auto-growth settings. In Listing 2 I provide the script I use to identify databases that use the default auto-growth settings.
Listing 2: Identify databases that have default auto-grow settings
The script in listing 2 uses an undocumented system stored procedure sp_MSforeachdb stored procedure to get the auto-growth setting from the sysfiles system table within each database, and store that information into a temporary table. Note the sp_MSforeachdb system store procedure has a bug in the code that causes it to sometime to not process through each and every database. Aaron Bertrand has noted this bug in his blog and has identified alternative method for processing through all databases with a T-SQL script: http://sqlblog.com/blogs/aaron_bertrand/archive/2010/02/08/bad-habits-to-kick-relying-on-undocumented-behavior.aspx. If you really want to make sure this code doesn’t randomly skip databases then I would suggest you implement a solution similar to solution to the one that Aaron’s documented in the link above when processing through your databases. For the case of displaying databases that are using the default auto-grow settings doing this is not critical but you still might miss databases.

Changing the Auto-grow settings of an Existing Database

Like most SQL Server settings, you can change them using either SQL Server Management Studio GUI tool, a script using SMO, or you can write T-SQL to modify them. To change the auto-growth setting in SQL Server Management Studio, first right click on the database for which you want to change the auto-growth settings and then click on the “Properties” item in the menu that is displayed. This will bring up the “Database Properties” dialog box for the database you selected. Next click on the “Files” item in the left pane under the “Select a page” section, this will display the database file information in the right pane. To get to the window where you can actually change the auto-growth setting, click on the button containing the 3 dots (“…”) or commonly referred to as the ellipses button. That will bring up the “Change Autogrowth…” window as seen in Figure 2. In the “Change Autogrowth…” window you can change the auto-grow settings for your database, just like you would when you create a database using SQL Server Management Studio. In Listing 3 I have provided a SQL statement that changes the FILEGROWTH settings for a database named “MyDB”.
Listing 3: Change the Auto-growth setting using T-SQL
In the ALTER DATABASE statement in Listing 3 I set FILEGROWTH size of the transaction log file named “MyDB_Log” in database MyDB to 20 MBs. You can use the ALTER DATABASE MODIFY FILE option to set the auto-growth numbers for any one of the files (DATA and/or transaction Log) associated with a database.

Identifying How Often an Auto-growth Event has Occurred

When SQL Server performs an auto-grow event, the transaction that triggered the auto-grow event will have to wait until the auto-grow event completes before the transaction can finish. These auto-growth events cause your performance to degrade a little when an auto-grow event is taking place. For this reason it is best if you can size your database appropriately so auto-growth events rarely occur.
If you are interested in how often an auto-growth event occurs on your system you can capture those events using a trace. By knowing which databases are performing auto-growth events allows you to adjust those database file growth properties so they will perform auto-growth events less frequently. You can use the profiler “Data File Auto-grow” and/or the “Log File Auto-grow” events to track these database auto-growth events. If you are running SQL Server 2005 or above, both these auto-grow events are already being captured by the default trace. If you haven’t turned off the default trace then you can use the default trace file to find these auto-grow events. If you have turned off the default trace you can either enable it, or setup a new profiler trace to capture the “Data File Auto-grow” and “Log File Auto-grow” events.
The default trace logs to a file. I have provided the code in Listing 4 to show you how to extract all the auto-growth events from the default trace files. If you create your own profiler trace session to capture these auto-grow events then you will need to modify this script to meet your profiler trace settings.
Listing 4: Display Auto-growth Events Contained in the Default Trace files
The code in Listing 4 identifies the name of the current trace file by using the fn_trace_getinfo function. Since the default trace might have multiple rollover files, I have to rip apart the file name so I can get the file name without the rollover number included. The code then passes the file name to the fn_trace_gettable function to return the profiler trace information from all the different rollover trace files. By using the output produced by this code you can identify what databases have had auto-growth events and when those auto-growth events have occurred. If this code doesn’t produce any auto-growth events then that means your instance doesn’t have any auto-growth events captured in the existing default trace files. In Report 1 I have provided a sample of the output produced by the code in Listing 4.
Report 1: Sample Output of the Data and Log Auto-growth Events
If you really want to keep a close eye on your auto-growth events you could create a SQL Agent job that sends you email about recent auto-growth events. The SQL Agent job could be run as a routine, and should execute some code similar to the code in Listing 4 that would show all auto-growth events since the last time the SQL Agent job ran. In Listing 5, I’ve provided a sample of some code that you could put in your SQL Agent job.
' +
    N''
+
    N' Start TimeEvent Name' +
    N'Database NameFile NameGrowth in MB' +
    N'Duration in MS
' +
    CAST((SELECT
              td = ftg.StartTime, '',
              td = te.name, '',
              td = DB_NAME(ftg.databaseid), '',
              td = Filename, '',
              td =(ftg.IntegerData*8)/1024.0, '',
              td = (ftg.duration/1000)
          FROM ::fn_trace_gettable(@filename, DEFAULT) AS ftg
               INNER JOIN sys.trace_events AS te ON ftg.EventClass = te.trace_event_id  
          WHERE (EventClass = 92  -- Date File Auto-grow
              OR EventClass = 93) -- Log File Auto-grow
             AND StartTime > DATEADD(dy,-1,GETDATE()) -- Less than 1 day ago
          ORDER BY StartTime  
          FOR XML PATH('tr'), TYPE
    ) AS NVARCHAR(MAX) ) +
    N'
' ;
    
 
    
    -- Build the subject line with server and instance name
    SET @Subject = 'Auto-grow Events in Last Day ' +
                   CAST(SERVERPROPERTY('MachineName') AS NVARCHAR(128)) +
                 + CASE WHEN SERVERPROPERTY('InstanceName') IS NULL
                        THEN ''  
                        ELSE N'\' +  CAST(SERVERPROPERTY('InstanceName') AS NVARCHAR(128))
                   END
 
    -- Send email to distribution list.    
    EXEC msdb.dbo.sp_send_dbmail @recipients=@DL,
           @subject = @Subject,  
           @body = @ReportHTML,
           @body_format = 'HTML',
           @profile_name='Server_DBAs Mail' ;
END; -- If there are autogrows in the last day
Listing 5: Email the Auto-growth events that have occurred in the last 24 hours to the DBA
The code in Listing 5 shows all the auto-growth events that have occurred in the last 24 hours. If an auto-growth event is found then it emails me a report of the auto-growth events.

Don’t let your Auto-growth Events Run Wild

Auto-growth events are expensive operations that slow down the performance of your database. Take the following preventive steps to ensure your auto-growth events do not run wild:
  • Pre-Size your databases and establishing appropriate auto-growth settings for your databases based on their growth profile.
  • Minimize future auto-growth events by monitoring the growth of your databases, and re-establishing auto-growth settings when a database growth profile changes.
  • Monitor auto-growth events so you can be alerted when your databases grow.
  • Consider defragmenting your database file system if you have let your auto-growth run wild.
Taking these preventive and proactive measures will help improve your database performance and better manage your disk space utilization.


Comentários

Mensagens populares