最近常常被问到的一个问题是关于在数据库维护过程,重建索引与更新统计的执行前后次序。一般,须要考虑如下几点,这里注意的是有两种统计:索引统计、列统计。html
1)默认状况下,UPDATE STATISTICS 将会更新索引统计和列统计,若是语句中仅使用了COLUMNS选项,则只更新列统计,若仅使用了INDEX选项,则只更新索引统计数据库
2)默认状况下,UPDATE STATISTICS语句仅采样表的一部分数据,使用UPDATE STATISTICS WITH FULLSCAN则会扫描全表ui
3)重建索引(如使用ALTER INDEX … REBUILD语句)仅更新索引统计,其效果至关于第2状况(WITH FULLSCAN),重建索引不会更新任何列统计url
4)重组索引(如使用ALTER INDEX … REORGANIZE语句)不更新任何统计3d
综上所述,最简单的状况是:重建索引并更新统计;正如上面提到的,若是重建索引,则索引统计也会经过扫描整个表的行被一同更新,那么只需再运行UPDATE STATISTICS WITH FULLSCAN, COLUMNS语句来更新列统计。htm
既然第一步仅更新了索引统计,第二步仅更新了列统计,两者执行的前后顺序并不重要。blog
其余较为复杂的状况是:基于碎片级的重建索引,固然,最坏的状况:若是首先重建了索引(仅扫描整张表的方式更新了索引统计,紧接着使用UPDATE STATISTICS语句(无任何参数),则会又执行了一遍索引统计。索引
下面经过AdventureWorks示例数据库为例来介绍这些命令的工做方式。get
首先运行如下脚本,建立临时表dbo.SalesOrderDetailit
SELECT * INTO dbo.SalesOrderDetail FROM sales.SalesOrderDetail
下面使用sys.stats 系统视图来查询新表的统计状况。
SELECT name, auto_created, stats_date(object_id, stats_id) AS update_date FROM sys.stats WHEREobject_id = object_id('dbo.SalesOrderDetail')
因为是一张新表,并没有任何查询,因此没有统计结果,下面执行如下的查询来产生一些统计:
select * from dbo.SalesOrderDetail where SalesOrderID = 43670 and OrderQty =1
再运行先前的查询系统视图的语句,咱们会发现系统为SalesOrderID和OrderQty两列建立了以_WA_Sys命名的两个列统计。
下面再运行建立索引的语句:
create index ix_product_id on dbo.SalesOrderDetail ( ProductID)
再运行系统视图的查询:
经过上图中的"auto_created"能够知道哪些统计是由系统建立的,下面运行以下语句只更新列统计,能够经过update_date列来检查。
update statistics SalesOrderDetail with fullscan, columns
接着运行更新索引统计的语句:
update statistics SalesOrderDetail with fullscan, index
下面两条语句的执行效果是同样的(更新索引统计和更统计)
update statistics SalesOrderDetail with fullscan
update statistics SalesOrderDetail with fullscan, all
下面再运行索引重建的方式来进行比较:
alter index ix_product_id on dbo.SalesOrderDetail rebuild
最后咱们来运行“重组索引”检查是否更新了统计:
ALTER INDEX ix_product_id ON dbo.SalesOrderDetail REORGANIZE
由此发现,执行索引重组并未更新任何统计。