SQL Server index tuning for peak performance

You can¶t just create your indexes randomly. They need to contain the right number of the right types of columns. It¶s a slippery slope. The wider the index is, the larger it is. The larger the index is, the slower it is. Slower indexes take longer to load from the disk, which means it will take SQL Server longer to process data in the index. Make sure that the only columns you index are those used to filter data, such as columns found in the WHERE clause of your query. Any columns that are being returned as part of the SELECT statement, or used to JOIN to child tables, should be added to the index as INCLUDE columns. For example, the following index query contains the correct columns.
SELECT LastName, FirstName FROM dbo.Employee WHERE DepartmentId = 4 CREATE INDEX IX_Employee_DepartmentId ON dbo.Employee (DepartmentId) INCLUDE (LastName, FirstName)

Below is a more complex query that includes the JOIN column in order to get a better view into columns that should be incorporated as either indexed columns or included columns.
SELECT e.LastName, e.FirstName, t.TeamName FROM dbo.Employee e JOIN dbo.Team t ON e.TeamId = t.TeamId WHERE e.DepartmentId = 4 CREATE INDEX IX_Employee_DepartmentId ON dbo.Employee (DepartmentId) INCLUDE (LastName, FirstName, TeamId) CREATE INDEX IX_Team_TeamId ON dbo.Team (TeamId) INCLUDE (TeamName) When indexes go bad

³If too many supplement pages are added, SQL Server might decide that the index cannot be used quickly enough to improve query performance. As a result, it will stop using it. This is where you come in.´ -- Don Jones, Microsoft MVP In this example, the index was created on the DepartmentId column because that is the column that we¶re filtering against. We then included the LastName and FirstName columns as the INCLUDE column because the SELECT statement returns those columns. The TeamId column was included because it¶s being used as part of the JOIN statement. On the Team table, the TeamId column is the indexed column and the TeamName column was included so that this column can be returned. While this query could be easily handled by the clustered index that is created on the Primary key, it might be more efficient to create a non-clustered index on the TeamId column and include the TeamName column. This will create a narrower index than the clustered index, which would decrease the number of data pages that would have to be loaded from the data table.

the index requires more space on the disk than it actually needs. If your index should be 10 MB. including the far side of the disk (Figure 1). Below is an example of the query and index.Employee (DepartmentId) INCLUDE (LastName.Employee WHERE DepartmentId = 4 CREATE INDEX IX_Employee_DepartmentId ON dbo. the physical data pages that make up the index end up fragmented. CREATE INDEX IX_Employee_DepartmentId ON dbo. which would give this index priority over one without the filter. This is especially helpful with larger tables. SQL Server can reduce or eliminate index fragmentation by using the white space to put new values in while new records are added or as existing records are updated in the index. After SQL Server has filled a data page. While having filtered indexes will increase your database storage requirements. FirstName) WHERE DepartmentID = 4 WITH (FILLFACTOR=70) The importance of index maintenance Not performing index maintenance is almost as bad as not having indexes on your table at all. a fill factor of 10% means your index will actually be about 11 MB. because of the white space requirement. This filtered index creates a much smaller index that loads from the disk faster than an index containing all of the records on the table. FirstName FROM dbo. Moving the data around to open up this white space requires the indexes to be rebuilt or reorganized on a regular basis. the SQL Server engine will detect that the index is not only a column match for the query but that it is also a filter match. especially in SQL Server. Understanding the fill factor setting The fill factor setting tells SQL Server to leave a certain amount of white space in the data page when you are building. the next page that it selects can be located anywhere on the disk. though over time data pages will become full and SQL Server will have to pick the next available data page to write data to. If you leave this space free when the index is created. rebuilding or defragmenting an index. . SELECT LastName. You can set the fill factor setting when the index is being created using the CREATE INDEX statement (shown below) or while rebuilding the index using the ALTER INDEX statement. the performance improvement for queries that would otherwise have to query large indexes should be sufficient enough to warrant the additional costs.Employee (DepartmentId) INCLUDE (LastName.Controlling index length in SQL Server 2008 Including a WHERE clause when you create the index allows you to control the index length and creates a filtered index with just a subset of the data in the table. The data will always be stored in the correct order within each data page. However. FirstName) WHERE DepartmentID = 4 When you execute this query. Without database maintenance. SQL Server doesn¶t maintain this amount of free space on its own. But nothing is free. The downside to setting the fill factor is that.

sys.user_lookups.database_id =DB_ID() and user_scans = 0 . which can cause a slowdown while that data page is loaded from the disk. To find the indexes that aren¶t being used.indexes.index_id ANDsys. Because of this erratic data movement. sys. Before the introduction of filtered indexes.indexes. slowing SQL Server even further while attempting to load the index data from the disk. UPDATE and DELETE statements.name notlike'PK%' ANDOBJECT_NAME(sys.dm_db_index_usage_stats joinsys.dm_db_index_usage_stats.indexes. query the sys.dm_db_index_usage_stats.indexesonsys. fewer indexes need to be updated. However.indexes. Failure to rebuild the page will lead to index fragmentation and will slow SQL Server¶s ability to move data around the index. With filtered indexes in place.dm_db_index_usage_stats. this meant that every change impacted every index.dm_db_index_usage_stats. which must be done for each data change. That will reduce the database¶s I/O requirements as well the size of the database.name. and this new data page is on the far outer edge of the disk. sys.dm_db_index_usage_stats dynamic management view using a query such as the one shown below. data will be spread all over the data file.object_id)<>'sysdiagrams' wheresys.object_id AND sys.object_id=sys. Remove indexes to boost performance Having indexes on a database table negatively affects the database. every index that contains the rows in question must also be updated to reflect this change.dm_db_index_usage_stats.indexes.dm_db_index_usage_stats.dm_db_index_usage_stats.Figure 1 (click to enlarge) The table data has been written to the outer rings of the disk and the index has been written to the inner rings of the disk. the indexes that contain the records still must be updated each time the rows change. sys. you should remove indexes from the database that aren¶t used to query data from the tables. You can see this negative performance when writing changes to the table through INSERT.indexes. index_id =sys. Because of this work. SelectOBJECT_NAME(sys. Each time you write a change to a table.user_seeks. But SQL Server had to allocate a new data page to the disk. sys.user_updates fromsys.object_id) TableName.user_scans.

.dm_db_index_usage_stats. Separating non-clustered indexes from the base table will offload storage and I/O requirements of the indexes from the tables that the indexes are based on to the other file group. Indexes also require maintenance to keep them working to their fullest potential or eventually they will slow down. if any at all. Most people believe indexes are generally beneficial. When creating the physical file for this secondary file group. sys. but they do have an effect on system performance² both good (increase response time for finding rows through select operations) and bad (inserting. Having multiple file groups in your database increases the management overhead of the database.indexes. This can decrease the amount of time it takes to make changes to your indexes. on a different file group from the table. updating or deleting rows).and user_scans = 0 and user_lookups = 0 and user_seeks = 0 andsys. in the end. If you attempt to create a clustered index. it may actually be slower to process a query with the index than without it. be sure to place the files on another set of physical disks so that the workload is actually moved to different spindles.name Creating file groups One great way to improve index performance is to create one or more file groups where you can store nonclustered indexes.object_id). the improvement is worth the work. then you won¶t see much performance gain.1) ORDERBYOBJECT_NAME(sys. If you wait long enough.index_id NOTIN(0. If both physical files are placed on the same physical spindles. but. Only non-clustered indexes can be stored in a different file group than the table that the index is built on. whether or not it¶s the primary key.indexes. then SQL Server will move the table to this new file group.

Sign up to vote on this title
UsefulNot useful