Login or Sign Up to become a member!
LessThanDot Sit Logo

LessThanDot

Data Management

Less Than Dot is a community of passionate IT professionals and enthusiasts dedicated to sharing technical knowledge, experience, and assistance. Inside you will find reference materials, interesting technical discussions, and expert tips and commentary. Once you register for an account you will have immediate access to the forums and all past articles and commentaries.

LTD Social Sitings

Lessthandot twitter Lessthandot Linkedin Lessthandot friendfeed Lessthandot facebook Lessthandot rss

Note: Watch for social icons on posts by your favorite authors to follow their postings on these and other social sites.

Your profile

    Search

    XML Feeds

    Google Ads

    « SQL Advent 2012 Day 2: Data types storage differencesUtilizing SQL Server Reports from SSMS »
    comments

    This post will demonstrate that there is a difference in performance if you don't size your database file accordingly. It is a good practice to have your database sized correctly for the next 6 to 12 months, you don't want your server wasting cycles with growing files all the time. Figure out how big your files are now, figure out how much they will grow in the next year and size your files accordingly, check back every month or so to see if your estimates were correct.

    By default SQL Server will create databases wilt very small files when you create a database and you don't specify the sizes. If you have people creating databases on your servers, consider adding a DDL trigger to notify you when a new DB is added so that you can talk to the database creator and size the files. You also can change the defaults on the server so that you don't have the 10% growth either.

    First let's see what the difference is when we have a database where the files will have to grow versus one where the files are big enough for the data that will be inserted.

    Here we are creating two databases, one with much bigger files than the other one

    This DB is correctly sized for the data that will be inserted

    1. CREATE DATABASE [TestBigger]
    2.  ON  PRIMARY
    3. ( NAME = N'TestBigger', FILENAME = N'f:\Temp\TestBigger.mdf' ,
    4. SIZE = 509600KB , FILEGROWTH = 1024KB )
    5.  LOG ON
    6. ( NAME = N'TestBigger_log', FILENAME = N'f:\Temp\TestBigger_log.ldf' ,
    7. SIZE = 502400KB , FILEGROWTH = 10%)
    8. GO

    This database is very small and will have to be expanded many times to accommodate all the data I will be inserting later on

    1. CREATE DATABASE [TestSmaller]
    2.  ON  PRIMARY
    3. ( NAME = N'TestSmaller', FILENAME = N'f:\Temp\TestSmaller.mdf' ,
    4. SIZE = 1280KB , FILEGROWTH = 1024KB )
    5.  LOG ON
    6. ( NAME = N'TestSmaller_log', FILENAME = N'f:\Temp\TestSmaller_log.ldf' ,
    7. SIZE = 504KB , FILEGROWTH = 10%)
    8. GO

    [edit]
    On sql server 2012, you might need to make the size of the 'TestSmaller file larger

    If you get an error like the following

    Msg 1803, Level 16, State 1, Line 1
    The CREATE DATABASE statement failed. The primary file must be at least 4 MB to accommodate a copy of the model database.

    Make the size of the primary file bigger, change the bold part from 1280KB to 5280KB or bigger if you still get the error

    NAME = N'TestSmaller', FILENAME = N'f:\Temp\TestSmaller.mdf' ,
    SIZE = 1280KB , FILEGROWTH = 1024KB

    [/edit]

    These two stored proc calls are just to verify that the files match with what we specified, you can use sp_helpdb to check the size of a database that you created when you don't specify the file sizes

    1. EXEC sp_helpdb 'TestBigger'
    name	        filename	            filegroup	SIZE
    TestBigger	f:\Temp\TestBigger.mdf	     PRIMARY	509632 KB
    TestBigger_log	f:\Temp\TestBigger_log.ldf	NULL	502400 KB


    1. EXEC sp_helpdb 'TestSmaller'
    name	        filename	             filegroup	SIZE
    TestSmaller	f:\Temp\TestSmaller.mdf	     PRIMARY	1280 KB
    TestSmaller_log	f:\Temp\TestSmaller_log.ldf	NULL	 512 KB



    Next, we are creating two identical tables, one in each database

    1. USE TestSmaller
    2. GO
    3. CREATE TABLE test (SomeName VARCHAR(100), SomeID VARCHAR(36), SomeOtherID VARCHAR(100), SomeDate DATETIME)
    1. USE TestBigger
    2. GO
    3. CREATE TABLE test (SomeName VARCHAR(100), SomeID VARCHAR(36), SomeOtherID VARCHAR(100), SomeDate DATETIME)

    This query is just used so that the data is cached for the two inserts later on, this way the data doesn't have to be fatched from disk for either inserts, you can discard the results after the query is done

    1. USE master
    2. GO
    3.  
    4.  
    5. SELECT TOP 1000000 c1.name,NEWID(),NEWID(),GETDATE()
    6. FROM sys.sysobjects c1
    7. CROSS JOIN sys.sysobjects c2
    8. CROSS JOIN sys.sysobjects c3
    9. CROSS JOIN sys.sysobjects c4

    Here is the first insert into the bigger database

    1. INSERT TestBigger.dbo.test
    2. SELECT TOP 1000000 c1.name,NEWID(),NEWID(),GETDATE()
    3. FROM sys.sysobjects c1
    4. CROSS JOIN sys.sysobjects c2
    5. CROSS JOIN sys.sysobjects c3
    6. CROSS JOIN sys.sysobjects c4

    Here is the second insert into the smaller database

    1. INSERT TestSmaller.dbo.test
    2. SELECT TOP 1000000 c1.name,NEWID(),NEWID(),GETDATE()
    3. FROM sys.sysobjects c1
    4. CROSS JOIN sys.sysobjects c2
    5. CROSS JOIN sys.sysobjects c3
    6. CROSS JOIN sys.sysobjects c4

    On several machines I tested on, it takes half the time or less to insert the data in the bigger database compared to the smaller database. How about on your machine, do you see that the insert into the bigger database takes less than half the time it takes to insert into the smaller database?

    Check the sizes of the databases again

    1. exec sp_helpdb 'TestBigger'
    name	        filename	           filegroup	size
    TestBigger	f:\Temp\TestBigger.mdf	     PRIMARY	509632 KB
    TestBigger_log	f:\Temp\TestBigger_log.ldf	NULL	502400 KB


    1. exec sp_helpdb 'TestSmaller'
    name	        filename	             filegroup	size
    TestSmaller	f:\Temp\TestSmaller.mdf	     PRIMARY	215296 KB
    TestSmaller_log	f:\Temp\TestSmaller_log.ldf	NULL	427392 KB



    As you can see, the bigger database did not expand, the smaller database expanded a lot.

    Autogrow
    If you do use autogrow, then make sure you don't use the default 10%, take a look at this message

    Date 11/30/2012 12:57:56 PM
    Log SQL Server (Current - 11/25/2012 5:00:00 AM)

    Source spid62

    Message
    Autogrow of file 'MyDB_Log' in database 'MyDB' took 104381 milliseconds. Consider using ALTER DATABASE to set a smaller FILEGROWTH for this file.

    See that, it took a long time, you don't want to grow a one terabyte file by ten percent, that would be one hundred gigabytes, that is huge. Use something smaller and don't use percent, the bigger the file gets the longer it will take to expand the file.

    File placement
    Separate the log files from the data files by placing them on separate hard drives. Placing the files on separate drives allows I/O activity to occur at the same time for both the data and log files. Instead of having huge files consider having smaller files in separate filegroups. Put different tables used in the same join queries in different filegroups as well. This will improve performance, because of parallel disk I/O searching for joined data.

    Put heavily accessed tables and the nonclustered indexes that belong to those tables on different filegroups. This will improve performance, because of parallel I/O if the files are located on different physical disks. Just remember that you can't separate the clustered indexes from the base table, you can only do this for non clustered indexes. Of course people can get very creative, I have worked with a database once where each table was placed in its own filegroups, there were hundreds of files....what a mess

    Tempdb
    There are all kinds of recommendations about how many data files you should have for tempdb. Start with 4 files and add more files if you see contention. Paul Randal, has a detailed post here: A SQL Server DBA myth a day: (12/30) tempdb should always have one data file per processor core.
    If you can, place tempdb on its own physical drive as well, separated from the user databases.

    Test, test, test
    Never ever blindly follow what you read on the internet, make sure that you test it out first on a QA server before promoting the changes to production!!




    That is all for day one of the SQL Advent 2012 series, come back tomorrow for the next one, you can also check out all the posts from last year here: SQL Advent 2011 Recap

    About the Author

    User bio imageDenis has been working with SQL Server since version 6.5. Although he worked as an ASP/JSP/ColdFusion developer before the dot com bust, he has been working exclusively as a database developer/architect since 2002. In addition to English, Denis is also fluent in Croatian and Dutch, but he can curse in many other languages and dialects (just ask the SQL optimizer) He lives in Princeton, NJ with his wife and three kids.
    Social SitingsTwitterFacebookLinkedInHomePageFlickrLTD RSS Feed
    3146 views
    InstapaperVote on HN

    2 comments

    Comment from: jamiet [Member] Email
    jamiet Nice stuff Denis, I like short sharp nuggets like this. My results:
    TestBigger: 5seconds
    TestSmaller: 69seconds

    Methinks this laptop needs some beefier disks :)

    One thing that might be interesting to you, when I ran your script to create TestSmaller I got:
    "Msg 1803, Level 16, State 1, Line 2
    The CREATE DATABASE statement failed. The primary file must be at least 5 MB to accommodate a copy of the model database."

    Perhaps a new thing in SQL2012?

    regards
    Jamie
    12/01/12 @ 14:34
    Comment from: SQLDenis [Member] Email
    SQLDenis Thanks Jamie,

    I added a small section detailing what to do if you get that error
    12/01/12 @ 16:28

    Leave a comment


    Your email address will not be revealed on this site.

    To mislead the spambots.

    Your URL will be displayed.
    (Line breaks become <br />)
    (Name, email & website)
    (Allow users to contact you through a message form (your email will not be revealed.)