DOWNLOAD THE CODE:
Download the Code 43783.zip

Performing routine database maintenance such as reindexing is important for keeping your databases running at peak performance. When you use INSERT, UPDATE, and DELETE statements to modify table data, indexes can become fragmented. Index fragmentation can happen when the logical sequence of pages is disrupted or when an index page contains less than its maximum amount of data, creating a gap in the data page or index. As indexes become fragmented, you get inefficient data reads when accessing tables and slower database performance.

But reindexing database tables takes time, and many DBAs already have limited time to complete such necessary maintenance jobs. One way DBAs can decrease the time required for maintenance is to reindex database tables according to set thresholds or limits. For instance, in a table that has 10 indexes, only two might be fragmented and require reindexing. If you run the DBCC DBREINDEX command without specifying individual indexes to be rebuilt or as part of the SQL Server scheduled maintenance plan job, the command will rebuild all 10 indexes. But if you rebuild only the two fragmented indexes, you save time and resources. By using the utility I describe in this article, you can rebuild only indexes that meet certain requirements.

You can determine when an index needs to be rebuilt by running the DBCC SHOWCONTIG command and looking at the values the command returns for Logical Scan Fragmentation, Extent Scan Fragmentation, and Scan Density. Logical Scan Fragmentation represents the percentage of pages that DBCC SHOWCONTIG finds out of order when it scans an index's leaf pages. Extent Scan Fragmentation represents the percentage of out-of-order extents DBCC SHOWCONTIG finds when it scans the leaf pages of an index. For both the Logical Scan Fragmentation and Extent Scan Fragmentation values, the lower the percentage the better. Conversely, the Scan Density value is the ideal number of extent changes if all pages and extents are contiguously linked and ordered properly. The closer this value is to 100 percent, the better. So if eight of a table's 10 indexes have greater than 95 percent Scan Density and less than 1 percent Logical Scan Fragmentation, you probably don't need to rebuild those eight indexes because the index fragmentation is low.

The threshold values that you use to determine whether to rebuild an index can vary from index to index based on such factors as the size of the table and frequency of use. For example, a table that has 10 million rows might have great performance if its Logical Scan Fragmentation is less than 5 percent but start experiencing performance problems if that value rises above 5 percent. However, a table that has 10,000 rows might not experience performance problems until the Logical Scan Fragmentation value is greater than 15 percent, at which time you need to rebuild the index to regain lost performance. Because of this variation, you need to set thresholds for each index to minimize table-reindexing time.

This article's example shows how I use the results of the DBCC SHOWCONTIG command—specifically the Scan Density and Logical Scan Fragmentation values—to determine which indexes to rebuild on tables in the SQL Server 2000 Northwind sample database. For this example, I use a stored procedure to set each index's default threshold values to 80 percent for Scan Density and 10 percent for Logical Scan Fragmentation. Any index that has a Scan Density of less than 80 percent and a Logical Scan Fragmentation greater than 10 percent needs to be rebuilt. I store these threshold values in a table that I can update when I need to streamline database maintenance.

Setting a Baseline
The first step in automating reindexing is to determine a baseline of appropriate DBCC SHOWCONTIG values for each table index by rebuilding all indexes. The time you spend on this step will save you time later when you've automated index maintenance. After you have a baseline, you can use the results of DBCC SHOWCONTIG to determine appropriate threshold values for each index.

Smaller tables might require different thresholds than larger tables because the difference in the number of extents affects the results you get when you reindex a table. For example, a small table that has only two extents and one primary key index might produce a Scan Density value of 50 percent and a Logical Scan Fragmentation value of 0 percent even after you rebuild it. Therefore, reindexing this table would yield no benefit. But a large table that has hundreds of extents and one primary key index might produce a Scan Density value of 95 percent and a Logical Scan Fragmentation value of 11 percent after you reindex it. If you set the thresholds of both these tables to a Scan Density value of 80 percent and a Logical Scan Fragmentation value of 10 percent, every time the reindexing job executes, it will rebuild the indexes for both tables because the smaller table will always have a Scan Density value of less than 80 percent. Establishing a baseline lets you determine the best DBCC SHOWCONTIG values for each index. And as your tables change, you can update the threshold values to maximize performance.

Assembling the Parts
Once you have a baseline and have decided what threshold you want to set for your indexes, you can create a SQL Server job that determines which indexes the utility needs to rebuild. The utility I use for reindexing requires a new database (which I've named SHOWCONTIGDEMO in this example) and three tables (OBJECT_LIST, STAGE_OBJECT_DATA, and OBJECT_
DATA) to work. I've provided listings that contain the scripts you need to set up the job and the database and tables it uses. You can download the Web listings at http://www.sqlmag.com, InstantDoc ID 43783.

Web Listing 1 creates the SHOWCONTIGDEMO database to store the DBCC SHOWCONTIG values that the example stored procedures will collect from Northwind's tables. I put this new database on the same server as Northwind. Next, when you execute Web Listing 2's scripts in the SHOWCONTIGDEMO database, the scripts build the OBJECT_LIST, STAGE_OBJECT_DATA, and OBJECT_DATA tables. The scripts in Listing 1 build three stored procedures that insert and delete index data in these three tables and compare threshold levels to determine whether you need to rebuild an index. Web Listing 3's two scripts create Listing 1's stored procedures in the Northwind database. Finally, Listing 2's script, page 42, creates on the server a new SQL Server job named DBCC SHOWCONTIGDEMO.

   Prev. page   [1] 2     next page



You must log on before posting a comment.

If you don't have a username & password, please register now.

Reader Comments

There is an error in the listing 1 the stored procedure p_del_object_list_data is a select statement and not a delete as mentioned in the article

hmaandek

Article Rating 4 out of 5

Please specify the correct syntax for the stored procedure "p_del_object_list_data" in Listing 1.

mjmclean

Article Rating 4 out of 5

There appears to be a syntax error in Listing 1 ( line 11-12: SELECT FROM o FROM ...

and another at line 23-24: SELECT FROM l FROM ...

Should these be: SELECT * FROM ...

on both incidences?

dbbyleo

Article Rating 4 out of 5

I am also getting this when executing Listing 2:

Server: Msg 8145, Level 16, State 2, Procedure sp_add_job, Line 0 @SELECT_level is not a parameter for procedure sp_add_job.

dbbyleo

Article Rating 4 out of 5

Oh yeah...Listing 1 does NOT show any delete statements, yet article says it is suppose to delete obsolete records.

dbbyleo

Article Rating 4 out of 5

I was thinking of doing a similiar approach. One thing I do different is when a cluster index needs to be Reindex I do all the indexes on the table by not specifying the index name. I found the command runs quicker than if I just did the cluster index. The Profiler reports the read and write counts are higher but the duration is less.

dbird

Article Rating 5 out of 5

Very useful idea, the syntax errors in the p_del_object_list_data procedure invalidate its' usefulness.

mselway

Article Rating 2 out of 5

Very useful tool. But I am getting syntex errors when I implemented on production.

DBCC REINDEX syntex error. If you know the fix please let me know. I'm lazy to fix on my own.

r_angani

Article Rating 4 out of 5

not only are there syntax errors in listing 1, but there are also errors in p_REINDEX_check in that it doesnt encapsulate the table names in braces to prevent it from erroring when a table has a space or period in its name.

eigh

Article Rating 1 out of 5

Ditto. Errors in p_del_OBJECT_LIST_DATA limit the usefullness of the utility. I want to use it but make chages to use instead DBCC INDEXDEFRAG. Not knowing what the author was trying to do, means more time on my part. I would expect the listings in this Mag to work out of the box.

domodog

Article Rating 2 out of 5

The syntax error is easy to fix - just modify the select statements (select from o to something like select * --from o). I compiled everything,and the demo works great Anastasia

LoveDanger

Article Rating 4 out of 5

DBCC SHOWCONTIG WITH TABLERESULTS, ALL_INDEXES;

the above will give you better results without a cursor

mrweaver59

Article Rating 3 out of 5

A piece of crap - it just doesn't work - it won't even make the objects much less actually do something.

cduwel@thresholds.org

Article Rating 1 out of 5

Very useful article and seems to fill my needs.

msosis

Article Rating 5 out of 5