最近常常被問到的一個問題是關於在數據庫維護過程,重建索引與更新統計的執行前後次序。一般,須要考慮如下幾點,這裏注意的是有兩種統計:索引統計、列統計。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
由此發現,執行索引重組並未更新任何統計。