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.

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.

For more articles like this, sign up to the fortnightly Simple-Talk newsletter.

Tags: , , , , , , ,

  • 227543 views

  • Rate
    [Total: 190    Average: 4.3/5]
  • Feodor

    Default trace audit dashboard
    Greg, recently I developed a set of reports which run as custom reports in SSMS and query the Default trace, which is available per SQL Server instance in versions 2005 and later. The reports are called Default Trace Audit and can be downloaded from here: http://sqlconcept.com/tools/default-trace-audit-documentation-and-faq/

    I am mentioning this, because they give an easy way to overview the most recent file growths and shrinks.

    Feodor

  • Grant.Fritchey

    Nice one
    Excellent article Greg. Clarifies things nicely.

  • financial advice

    financial advice
    I will bookmark your blog and have my kids check up here frequently. I’m very certain they will understand lots of new stuff here than anybody else.

  • Pratik

    Excellent
    Excellent aricle

  • DoctorJools

    Further details?
    You say “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.”

    Do you have any further information about this, or possibly some figures? It would be great to have something to send to our customers who seem to think this doesn’t matter!

  • Anonymous

    thank you
    greate article, thank you!
    is it possible to identify the tables that causes the autogrowth of a file?

  • HolgerSchmeling

    sysfiles and sp_MSForeachdb
    Greg,
    nice article. I’ll definitely use some of your scripts.
    Just one marginal annotation: sysfiles is depricated and sp_MSForeachdb still undocumented. There’s a better and even clearer way to ask für db-file options via sys.master_files, like this:

    select db_name(database_id) as db
    ,name,type_desc,physical_name
    ,size
    ,max_size
    ,growth
    ,is_percent_growth
    from sys.master_files

    By using this query, you get all file information at once.

    Regards,
    Holger

  • Anonymous

    Instant File Initialization and Guidelines
    Good article, but you say that “processing against that database will be held up while the auto-growth event completed”. Is that not such a concern if utilizing instant file initialization? Can you clarify that in an update or something?

    Also, what are some numerical guidelines on how much to set the autogrowth to?

  • TheSQLGuru

    1MB Killer
    I have had numerous clients have the 1MB default growth for data files. One had almost 400000 file fragments for their data files. Defrag OS file system – double-digit perf improvement in IO performance!

  • Anonymous

    JackDonnell
    Great Article!

    I use an version of this to get file info. I run different select statements against the resulting #DATA_FILE_SIZING table. The table becomes useful to find summary of such things as total file size files by drives, free space within the data files and unrestricted growth .

    IF OBJECT_ID (‘tempdb..#FREE_SPACE_DRIVES’,’u’) IS NOT NULL
    BEGIN
    DROP TABLE #FREE_SPACE_DRIVES;
    END

    BEGIN
    CREATE TABLE #FREE_SPACE_DRIVES(
    DRIVE CHAR(1)PRIMARY KEY,
    FREESPACE BIGINT NOT NULL
    )
    END
    INSERT INTO #FREE_SPACE_DRIVES
    EXECUTE master.dbo.xp_fixeddrives;

    IF OBJECT_ID (‘tempdb..#DATA_FILE_SIZING’,’u’) IS NOT NULL
    BEGIN
    DROP TABLE #DATA_FILE_SIZING;

    END

    CREATE TABLE #DATA_FILE_SIZING (
    [DBNAME] NVARCHAR (240) NULL,
    [NAME] [sysname] NOT NULL,
    [DRIVE] [nvarchar](1) NULL,
    [FILELOCATION] NVARCHAR (240) NOT NULL,
    [FILEID] [smallint] NULL,
    [FILEGROUP] [nvarchar](128) NULL,
    [FILESIZE(GB)] [decimal](16,4) NULL,
    [SPACEUSED(GB)] [decimal](16,4) NULL,
    [FREESPACE(GB)] [decimal](16,4) NULL,
    [MAXFILESIZE(GB)] [decimal](16,4) NULL,
    [GROWTHSIZE(GB)] [int] NULL,
    [islogfile] [int] NULL,
    [CanGrow] [int] NULL,
    [SampleDateTime] [datetime] NOT NULL
    )

    DECLARE @sqlFILESIZE VARCHAR(MAX)

    SET @sqlFILESIZE =
    ‘USE [?] SELECT ”[”+RTRIM(DB_NAME())+”]” [DBNAME],RTRIM(a.name) as [NAME]
    ,UPPER(SUBSTRING(a.FILENAME,1,1)) as [DRIVE]
    ,a.FILENAME as [FILELOCATION]
    ,a.FILEID
    ,CASE WHEN FILEPROPERTY (a.name ,”islogfile”)= 0 THEN FILEGROUP_NAME(a.Groupid) ELSE ”LOG” END [FILEGROUP]
    ,CONVERT(decimal(12,2),ROUND(a.size/128.000,2)/1024) [SIZE GB]
    ,CONVERT(decimal(12,2),ROUND(fileproperty(a.name,”SpaceUsed”)/128.000,2)/1024) as [SPACEUSED]
    ,CONVERT(decimal(12,2),ROUND(a.size/128.000,2)) – CONVERT(decimal(12,2),ROUND(fileproperty(a.name,”SpaceUsed”)/128.000,2)/1024)as [FREESPACE]
    ,CASE WHEN a.maxsize = ”-1” and a.growth<>0 then 2097152.0000
    WHEN Growth = 0 THEN CONVERT(decimal(12,2),ROUND(a.size/128.000,2)/1024)
    ELSE CONVERT(decimal(12,2),ROUND(a.maxsize/128.000,2)/1024) END as [MAXFILESIZE]
    ,CONVERT(decimal(12,2),ROUND(a.growth/128.000,2)/1024) [GROWTHSIZE]
    ,fileproperty(a.name,”islogfile”) islogfile
    ,CONVERT(DECIMAL(8,2),growth/1024) CanGrow
    ,GETDATE()[SampleDateTime]
    FROM dbo.sysfiles a;’

    — Insert all output into a table to
    INSERT INTO #DATA_FILE_SIZING
    Execute master.sys.sp_MSforeachdb @sqlFILESIZE;

    SELECT
    SERVERPROPERTY(‘ServerName’) [Instance],
    a.[DBNAME],
    a.[NAME],
    a.[DRIVE],
    CAST(b.FREESPACE/1024 as DECIMAL(8,2)) [DriveFreeSpace(GB)],
    a.[FILELOCATION],
    a.[FILEID],
    a.[FILEGROUP],
    a.[FILESIZE(GB)],
    a.[SPACEUSED(GB)],
    a.[FREESPACE(GB)],
    a.[MAXFILESIZE(GB)],
    a.[GROWTHSIZE(GB)],
    a.[islogfile],
    a.[CanGrow],
    SERVERPROPERTY(‘Edition’)[Edition],
    SERVERPROPERTY(‘ProductVersion’)[Version],
    a.[SampleDateTime]
    FROM #DATA_FILE_SIZING as a
    JOIN #FREE_SPACE_DRIVES as b
    ON a.[DRIVE]=b.[DRIVE];

    — Clean up
    IF OBJECT_ID (‘tempdb..#FREE_SPACE_DRIVES’,’u’) IS NOT NULL
    BEGIN
    DROP TABLE #FREE_SPACE_DRIVES;
    END

    IF OBJECT_ID (‘tempdb..#DATA_FILE_SIZING’,’u’) IS NOT NULL
    BEGIN
    DROP TABLE #DATA_FILE_SIZING;

    END

  • Anonymous

    Best practice for system dbs
    Hello, aside from TempDB are there recommended practices for the Master, MSDB, Model, & Resource dbs for configuring settings including Auto Growth?

  • Nicole

    Setting a Maximum File Size
    About a year ago I had some bad code on the development server chew up all the remaining disk space (some gigabytes) in a few seconds. This situation is rare but potentially quite disastrous. For that reason, I now set a Maximum File Size on all the databases, whether development or production. The Maximum File Size is set quite a bit larger than the database’s current size so that there is a lot of room for growth.

  • Nicole

    Monitoring Database File Size–Alerts
    You can get SQL Server to alert you whenever a file grows on a server. Just create a SQL Server performance condition alert for object: SQL Server:Databases, one alert each for counter: Data File(s) Size (KB) and counter: Log File(s) Size (KB), for Instance: _Total. It should alert if the counter rises above some small number. Then wait for it to alert you, and the alert will tell you the current value which you can then insert into the Value field in the alert properties dialogue box. Just remember to also go to the Options page and set the Delay between responses to something reasonable (I set it to either 240 or 480 minutes)!

  • Anonymous

    real time autogrowth monitoring
    Nice article, Greg!
    We monitor autogrowth in real-time with WMI alerts.

  • Jeff

    Thanks
    Thanks for the entry about creating an alert to do this.

  • Malerie

    YQdTvpccSHBEJFJ
    I was seirosuly at DefCon 5 until I saw this post.

  • Satishkumar

    Thanks from an accidental DBA
    Thank you very much Mr.Larsen. A wonderful explanation of auto-growth and how it is not a good idea to always go with default settings. I knew auto-growth existed but have been using it only to increase size of the DB. This article has taught how it can even affect performance.

  • uufevggmuc

    tKeaOOmHrZ
    8syvUM , [url=http://wxsltodrgvqq.com/]wxsltodrgvqq[/url], [link=http://ygxeodgciwqh.com/]ygxeodgciwqh[/link], http://gdfhdrtjppbh.com/

  • satish.setti

    Anonymous
    Thanks for sharing such a valuable information through posts or blogs whatever. thanks thanks to simple-talk.

  • giovanni.clayden

    SQL Server Database Growth and Autogrowth Settings
    Excellent article. Thanks for sharing

  • Thomas Roes

    The next step?!
    L.S.

    Good article. I’m waiting for the results on our Sharepoint system (and some others). But, why not take the next step.

    OK,
    – planning your database expected size is good,
    – good configuration of autogrowth is nessesary (in case your estimate way to low)
    – alerting on autogrowth good

    BUT

    autogrowth always slows down transactions. (too) Often if the autogrowth is (too) small, (too) long if the autogrowth is too big.

    Why not automaticly grow (or shrink) your database during the low-usage time window:
    – grow with 10% is free space is below 5%
    – shrink with 10% if free space is above 25%

    Not being a full-time SQL administrator, this will take me some time to figure out, but maybe an answer will appear…