Home About Us SQL Interview Book Contact Us RSS
Code Snippets
Tips & Tricks
Code Snippets

Saravana Kumar
Vinod Kumar

Database Storage with SQL Server – Part II 

This is in continuation to the storage story we had at http://www.extremeexperts.com/sql/articles/StoragePractice.aspx. With that as foundation let us take a step closer to other aspects to the storage system like what needs to be taken care when working with physical files, filegroups, transaction log design, SAN / RAID and more. We will cover as much as possible and let me highlight some of the best practices on the same lines.

User Databases Design

In Part I, we did discuss about the requirements and needs from a system databases side but here we will get started with the user controlled databases. When evaluating solutions, you should consider their affect on your high-availability requirements too. This is most often decided by the customers needs and I would like you to keep them in mind.

The location for storing the user databases depends on the hardware and the database solution. Generally, you should separate the random database file I/O from the sequential log file I/O. You cannot improve the performance by adding more files than the number of CPUs in your SQL Server environment, unless you provide additional physical storage devices. You should also design an appropriate filegroup strategy that provides parallel access to different physical devices when different database objects are stored in different filegroups that are created on different physical storage devices.

Once we get some fundamentals, you must be wondering the physical storage is based on the RAID / SAN configurations mostly. Let me callout some of the points to remember when working with RAID:

  • The vulnerability of a RAID array after a disk drive failure. This decides your RAID level.
  • Hardware support for hot-spare disk drives.
  • Time it takes to rebuild a RAID array.
  • The number of hot-spare disk drives the RAID array supports, and the number or ratio that you will be using.
  • A hardware RAID controller that meets the SQL Server I/O requirements.

You can use RAID 5 for data files, but it is not appropriate for log files. RAID 10 (stripe of mirrors) is a better choice than RAID 0+1 (mirror of stripes), because RAID 0+1 could fail if one disk on each side of the mirror fails. The probability of a RAID 10 array failing is much lower because it can handle more than one disk drive failure. You should NEVER use RAID 0 in a high-availability solution.

You should analyze the current space requirements and plan for future growth. The auto-growth process can make the system unavailable because SQL Server needs to get space from the disk drive. Auto-growth also causes external disk fragmentation, and therefore you should avoid it. You can read http://www.extremeexperts.com/SQL/Articles/AutoGrowth.aspx for more insight to what I am talking.

Structuring File / Filegroups

Filegroups and secondary database files are fundamental elements of an effective storage solution for high-availability databases. They can improve performance, simplify administrative tasks, and form the basis of your backup strategy. You need to design your filegroup strategy before you implement a high-availability database storage solution, because it can be difficult to change your strategy after the system has been placed in the production environment. Your strategy will vary, depending upon whether you are designing a file structure that is composed of multiple physical files or multiple logical filegroups.

Incase of multiple files here are some points to keep in mind:

  • Pre-allocate an appropriate size for database files. Auto-growth of database files has an impact on the performance as discussed before. By pre-allocating and monitoring the free capacity of database files, you can avoid performance issues during production hours.
  • Place multiple database files on separate drive arrays. You can improve performance and minimize disk contention by separating database files onto separate I/O channels. Ensure that you do not saturate the I/O bus.
  • Limit the number of database files to the number of CPUs. The maximum number of threads that SQL Server will utilize to access database files is equal to the number of CPUs included in your system, taking into account any affinity configuration settings.
  • Consider an appropriate maximum file size that is equivalent to your removable media. This will help the DBA to perform administrative tasks, such as moving a database, by detaching locally and attaching remotely.

Now if we make this as multiple logical files, use these as some pointers:

  • Store only the system tables on the PRIMARY filegroup. Separate your user data from the metadata by defining a new default filegroup. Create a set of secondary database files associated with this new filegroup.
  • Maximize performance by separating different I/O patterns. You can maximize performance with filegroups by separating your table data, Line of Business (LOB) data, and indexes onto different drive arrays. BTW, I would use exceptions for cases like partitioned tables where I would prefer same filegroup and keeping indexes aligned.
  • Design an appropriate backup strategy. SQL Server allows you to back up your user databases at the file or filegroup level. By designing an appropriate file or filegroup strategy, you can minimize the impact that backups have on your high-availability solution.
  • Minimize downtime during database file failure. SQL Server 2005 allows you to perform online file restores while the database remains online. While you are restoring a damaged file, the file and its filegroup will be offline. This feature is available only in SQL Server 2005, Enterprise Edition. Use NTFS compression to obtain only historical data that is rarely accessed.
  • Use NTFS compression on read-only filegroups for accessing historical data.

Note: You should generally avoid using NTFS compression on read-only filegroups because they are slower than uncompressed filegroups. Also, there are administrative overheads involved if you need to modify the data.

Transaction Log - Special case

The transaction log records all the database modifications that are made by each transaction. The transaction log file is made up of a number of Virtual Log Files (VLFs) that are used sequentially by the SQL Server database engine in a round-robin manner. Therefore, there is limited value in having multiple log files. You can use the DBCC LOGINFO command to identify the active VLFs, and you can use the sys.databases database catalog to determine why SQL Server is waiting to reuse transaction log space. You should remember that the amount of log file activity will also be affected by which database recovery model you use—simple, full, or bulk-logged. Use the following guidelines for designing file structures for transaction logs. Let us look at some of the characteristics for transaction logs:

Transaction log files are accessed sequentially by SQL Server, whereas database files are accessed randomly. Due to the serial architecture of the transaction log, you will not realize any performance gains by allocating multiple files on disk drives that are different from the disk drives for the transaction log. Consider creating an appropriate disk array and one transaction log file that spans the array to avoid data loss.

The transaction log of your database represents a potential bottleneck in your database solution. You should use faster and more expensive drives for your transaction logs. You should carefully determine the RAID solution that you will implement for your transaction log. The log is write-intensive in most SQL Server solutions. Therefore, you should not use RAID 5. You can use a RAID 1 or RAID 10 array for better performance.

Your storage solution should allow you to back up the tail-log in the event of a database failure. This will enable you to back up all the DML operations in your database after the last transaction log backup, thus avoiding any data loss in the event of a disk drive failure.

You need to allocate enough space and configure an appropriate monitoring and alerting solution to ensure that your transaction log does not run out of space.

RAID and SAN - Best Practices

Above we did talk about the logical entities, next we will move to the actual physical entity where we will land the actual files. The primary purpose of a RAID array is to prevent potential disk failures and help you store information redundantly to avoid data loss. It also improves the performance of the Input/Output subsystem by distributing the number of disk drives you use concurrently, and thereby improves the disk Input/Output throughput. There are many RAID levels to choose from, depending on the configuration of the database server. Each level has its advantages and disadvantages. All the disks in a RAID configuration function as one logical storage unit regardless of the RAID level used. Here are some points that you need to keep in mind while working with storage and SQL Server in particular.

RAID 0 provides performance improvements by striping data across multiple physical disks. However, this configuration does not provide fault tolerance. If one physical disk fails, the entire disk set fails and all the data is lost. Therefore, RAID 0 is not appropriate for database servers and high-availability solutions.

RAID 1 provides mirroring of data and fault tolerance. In a RAID 1 configuration, you need a minimum of two disks. Mirroring affects the performance of write operations because data is written to both disks at the same time. You can improve the performance of the read and write operations in RAID 1 by parallelizing these operations. Generally, SCSI RAID disk controllers can write to multiple disks simultaneously and thereby improve the performance of read and write operations. In a RAID 1 configuration, the storage capacity is exactly half of the total physical capacity available.

RAID 5 uses block-level striping and stores parity data in a different stripe section. You can use a simple XOR operation and store redundant data in the system so that you can recover the data in the event of a disk failure. If a disk drive fails, you can recover its data by performing an XOR operation on the parity data and the data in the other disk. The parity calculation produces some overhead. Therefore, RAID 5 is not recommended for write-intensive operations.

RAID 10 or RAID 1+0 is a stripe of mirrored or RAID 1 disks. With this approach, you can increase the Input/Output throughput by striping data, and you can protect the data by using mirroring. RAID 0+1 is a mirror of striping disks. RAID 0+1 is weaker than RAID 10 because if two drives on different sides of the mirror fail, the entire array of disks will fail. In RAID 10, the system will fail only if both the failed disks are members of the same mirror set.

A SAN is a shared repository for storing data. One or more servers can connect to a SAN device and access the data stored in it. In SQL Server clustering, a SAN provides common storage for a SQL Server instance that can run from any node in the cluster. The most common SAN configuration is Fibre Channel Networking with the SCSI command set. SAN devices using this technology appear to the servers as directly-attached storage devices. A SAN is compatible with all types of RAID configurations, but it may be configured differently, depending on the hardware vendor. It is a normal practice to virtualize different RAID configurations inside a SAN device. A different SAN configuration is iSCSI. It replaces Fibre Channel switches with Ethernet switches because Ethernet supports the IP protocol.

Note: Most hardware RAID solutions allow you to install spare drives that will be automatically used by the system when a disk fails. Your server can have more than one hot spare drive. Spare drives also allow you to schedule the replacement of damaged disks so that you can avoid the risk of another disk failure and data loss.

TempDB - Special Mention

The storage solution for the tempdb database should ensure a reliable performance. Secondly, a damaged disk here can bring the whole instance down. The storage requirements for this database depend on how you plan to utilize it. Certain SQL Server 2005 features, such as MARS, triggers, and snapshot-based isolation levels, are based on row–versioning and utilize the tempdb database. Therefore, you need to plan your storage solution accordingly.

You should store the tempdb database on a local disk array because it is I/O-intensive. You should not share this database with other I/O-intensive subsystems, such as the location where the Windows pagefile, temp directory, or other production databases are stored. In most database systems, the tempdb database supports intensive write activity and this might increase the load on some physical devices.

There is no need to store the tempdb database on a SAN for administrative purposes because it is rebuilt each time the SQL Server engine starts. However, if you still need to store the tempdb database on a SAN, the SAN technology that you have implemented would determine the performance. You should define multiple files that are stored in multiple physical drives for the tempdb database to minimize the resource load. You should create as many files as the number of physical CPUs that the server uses for SQL Server. In a system with 16 or more CPUs, you should start with a lower number of files, and increase this number until you reduce the load to a reasonable level.

You can use RAID 10 to store the tempdb database. Using a RAID 5 array is not appropriate because the tempdb database is write-intensive. It is also not appropriate to use a RAID 0 array in a high-availability solution because a drive failure could cause a SQL Server failure.


As always, when working with SQL Server it is a complete 360 view of your database that helps it scale and perform at its best. So this is just the starting and you can see we had so much to talk only for the storage system. I would urge you to keep monitoring and viewing reports for the storage system given by vendors from time-to-time to make sure your database / server remains healthy and you are able to get the problems well before they occur.