THE SQL Server Blog Spot on the Web

Welcome to - The SQL Server blog spot on the web Sign in | |
in Search

Benjamin Nevarez

Rebuilding Indexes vs. Updating Statistics

One of the questions I was asked recently while speaking at user groups, was regarding the order that jobs like rebuilding indexes or updating statistics should be performed as part of the database maintenance activities. Then I started writing this post about this topic on the weekend but was interrupted several times, including one of them to watch the premiere on VH1 of the movie Anvil: The Story of Anvil.


In general, the order should not matter, at least if you carefully consider these important points:


1) By default, the UPDATE STATISTICS statement uses only a sample of records of the table. Using UPDATE STATISTICS WITH FULLSCAN will scan the entire table.


2) By default, the UPDATE STATISTICS statement updates both index and column statistics. Using the COLUMNS option will update column statistics only. Using the INDEX option will update index statistics only.


3) Rebuilding an index, for example by using ALTER INDEX … REBUILD, will also update index statistics with the equivalent of using WITH FULLSCAN. Rebuilding indexes does not update column statistics.


4) Reorganizing an index, for example using ALTER INDEX … REORGANIZE, does not update any statistics.


So depending on your maintenance jobs and scripts several scenarios can exist.


The simplest scenario is if you want to rebuild all the indexes and update all the statistics. As mentioned before, if you rebuild all your indexes then all the index statistics will also be updated by scanning all the rows on the table. Then you just need to update your column statistics by running UPDATE STATISTICS WITH FULLSCAN, COLUMNS. Since the first job only updates index statistics and the second one only updates column statistics, it does not matter which one you execute first.


Some other more complicated scenarios include when you have a job which rebuilds your indexes depending on their fragmentation level. In these cases perhaps you want to update only those index statistics that were not touched by the index rebuild job, plus all the column statistics.


Of course, the worst case scenario would be if you first rebuild your indexes, which also updates the index statistics by scanning the entire table, and later you run UPDATE STATISTICS using the default values, which again updates the index statistics but this time with a default sample. Not only are you updating your index statistics twice but you are overwriting the better of the two choices.


Let me show you how these commands work with some examples using the AdventureWorks database. Create a new table dbo.SalesOrderDetail


select * into dbo.SalesOrderDetail

from sales.SalesOrderDetail


The next query uses the sys.stats catalog view and shows that there are no statistics objects for the new table.


select name, auto_created, stats_date(object_id, stats_id) as update_date from sys.stats

where object_id = object_id('dbo.SalesOrderDetail')


Use this query again to inspect the status of the statistics after each of the following commands. Now run the following query


select * from dbo.SalesOrderDetail

where SalesOrderID = 43670 and OrderQty = 1


Use the previous sys.stats query to verify that two statistics objects were created, one for the SalesOrderID column and another one for the OrderQty column (they both have names starting with _WA_Sys as shown in the next figure). Now create the following index and again run the query to verify that a new statistics object for the ProductID column has been created. Notice the value of the auto_created column which tells if the statistics were created by the query optimizer.


create index ix_ProductID on dbo.SalesOrderDetail(ProductID)




Run the next command to update the column statistics only. You can validate that only the column statistics were updated by looking at the update_date column which uses the STATS_DATE function to display the last date the statistics were updated.


update statistics dbo.SalesOrderDetail with fullscan, columns





This command will do the same for the index statistics


update statistics dbo.SalesOrderDetail with fullscan, index


These commands will update both index and column statistics


update statistics dbo.SalesOrderDetail with fullscan

update statistics dbo.SalesOrderDetail with fullscan, all


See how an index rebuild only updates index statistics


alter index ix_ProductID on dbo.SalesOrderDetail rebuild


Here you can verify that reorganizing an index does not update statistics


alter index ix_ProductID  on dbo.SalesOrderDetail reorganize


Finally, remove the table you have just created


drop table dbo.SalesOrderDetail

Published Tuesday, October 6, 2009 1:04 AM by Ben Nevarez
New Comments to this post are disabled

About Ben Nevarez

Benjamin Nevarez is a SQL Server MVP and independent consultant based in Los Angeles, California who specializes in SQL Server query tuning and optimization. He is the author of "SQL Server 2014 Query Tuning & Optimization" and "Inside the SQL Server Query Optimizer" and co-author of "SQL Server 2012 Internals". With more than 20 years of experience in relational databases, Benjamin has also been a speaker at many SQL Server conferences, including the PASS Summit, SQL Server Connections and SQLBits. Benjamin’s blog can be found at and he can also be reached by e-mail at admin at benjaminnevarez dot com and on twitter at @BenjaminNevarez.
Privacy Statement