天天看點

了解統計資訊(1/6):密度向量

在日常生活中,我們用統計資訊來采取決定。SQL Server優化器也用同樣的方式,使用統計資訊來選擇正确的執行計劃。如果統計資訊錯誤或過期,SQL Server可能就會選擇錯誤的執行計劃。在這個文章裡,我們換個方式了解下統計資訊。

查詢優化器使用統計資訊來判斷每一步傳回的行。執行計劃裡的估計行數資訊是基于列的可用統計資訊計算而來的。統計資訊給我們列裡資料分布情況。沒有統計資訊,查詢優化器不能夠判斷不同計劃的效率。通過使用統計資訊,查詢優化器在通路資料時可以做出正确的選擇。

在我們定義索引時,統計資訊會自動建立。除此之外,當列在查詢裡被引用,作為WHERE條件的一部分,在group by子句裡或join條件裡,統計資訊都會建立。為了自動建立統計資訊,在資料庫層裡的AUTO_CREATE_STATISTICS 設定應該被啟用。預設情況下這個設定是被啟用的。除此之外,統計資訊可以使用CREATE STATISTICS指令建立。

在SQL Server裡存儲的統計數字是關于密度向量和直方圖(資料分布)的資訊。在我們讨論更多細節前,先了解這2個概念。

密度向量:在給出列或一組列唯一值的比例。統計密度向量的公式:1/列(或一組列)不同值個數。

密度向量用來衡量列的唯一性或列的選擇性。密度向量的值在0和1之間。如果這列的密度值為1,表示這列的所有記錄值一樣,選擇性低。更高的密度帶來更低的選擇性。如果這列的密度值為0.003,表示這列有1/0.003=333個不同值。

我們來看個例子,用下列語句建立表并在上面建立2個索引。 

1 USE StatisticsDB
2 GO
3 
4 SELECT * INTO SalesOrderDetail FROM AdventureWorks2008R2.Sales.SalesOrderDetail
5 CREATE UNIQUE CLUSTERED INDEX ix_SalesOrderDetailID ON SalesOrderDetail(SalesOrderDetailID)
6 CREATE NONCLUSTERED INDEX ix_productid ON SalesOrderDetail(productid)      

我們來看看這2個索引的統計資訊。

1 DBCC SHOW_STATISTICS('dbo.SalesOrderDetail', 'ix_SalesOrderDetailID')      
了解統計資訊(1/6):密度向量

輸出結果有3個表,分别是:統計資訊頭,密度向量和直方圖。

了解統計資訊(1/6):密度向量

在第1部分(統計資訊頭)

  • Name :索引名稱
  • Updated :統計資訊更新時間
  • Rows :索引裡行數目。不是表裡的行數。
  • Rows Sampled :用于生成統計資訊的采樣行數。建立索引的時候,會進行完全掃描。
  • Steps :直方圖裡的步長。(第3部分的内容)
  • Density :在SQL Server裡不再使用,向老版本相容。
  • Average key length :索引鍵平均長度。
  • String Index :用于like時估計統計行數。
  • Filter Expression :過濾索引表達式
  • Unfiltered Rows :未過濾的行數,如果不存在過濾索引,則等同于Row列。

可以使用DBCC SHOW_STATISTICS加WITH STAT_HEADER來隻擷取統計頭資訊。

在第2部分的密度表,我們隻看到一條記錄,因為在我們索引裡隻有1列。

所有密度列給我們SalesOrderDetailsId 列的密度值(1/列(或一組列)不同值個數)。所有密度列給我們值 8.242868E-06 =0.000008242868。這表示SalesOrderDetailsId 列有 1/0.000008242868=121317個唯一值,我們可以用下列語句驗證下。

1 SELECT COUNT(DISTINCT SalesOrderDetailID ) FROM SalesOrderDetail      
了解統計資訊(1/6):密度向量

可以使用DBCC SHOW_STATISTICS加WITH DENSITY_VECTOR來隻擷取密度向量資訊。

我們來看看非聚集索引ix_productid的密度。

1 DBCC SHOW_STATISTICS('dbo.SalesOrderDetail', 'ix_productid') WITH DENSITY_VECTOR      
了解統計資訊(1/6):密度向量

在密度表裡可以看到2行記錄,即使我們的非聚集索引是在單列上。這是因為聚集鍵是非聚集索引的一部分(參見索引深入淺出(4/10):非聚集索引的B樹結構在聚集表)。

第一行告訴我們,ProductID 列的密度向量值為0.003759399,換句話說,在ProductID列有1/0.003759399=226個唯一值。我們可以驗證下。

1 SELECT COUNT(DISTINCT ProductID) FROM dbo.SalesOrderDetail      
了解統計資訊(1/6):密度向量

第二行告訴我們,ProductID和SalesOrderDetailID組合列的密度向量值是0.000008242868,換句話說,ProductID和SalesOrderDetailID組合列有121317個唯一值,這個和表的總記錄數是一緻的。

密度向量值會用在哪裡呢,我們看下下面查詢的執行計劃,點選工具欄的

了解統計資訊(1/6):密度向量

顯示包含實際的執行計劃。

1 SELECT ProductID,COUNT(*) FROM dbo.SalesOrderDetail GROUP BY ProductID      
了解統計資訊(1/6):密度向量

在執行計劃裡,在流聚合運算符的輸出裡,我們看到估計行數是266。在ProductID列唯一值(個數)可以從密度表裡拿到。但我們怎麼證明查詢優化器是用這個值來計算估計行數。我們建立另外一個沒有任何索引的SalesOrderDetail表。

1 SELECT * INTO SalesOrderDetail_NoStats FROM SalesOrderDetail      

通過下面語句我們可以看出,這表沒有任何的統計資訊。

1 EXEC SP_HELPSTATS 'SalesOrderDetail_NoStats', 'ALL'      
了解統計資訊(1/6):密度向量

我們再看下這個表的剛才查詢,點選工具欄的

了解統計資訊(1/6):密度向量

顯示包含實際的執行計劃:

1 SELECT ProductID,COUNT(*) FROM dbo.SalesOrderDetail_NoStats GROUP BY ProductID      
了解統計資訊(1/6):密度向量

在沒有任何統計索引和統計資訊的情況下,優化器再一次在流聚合運算符的輸出裡估計行數是266。我們再次檢查下這個表的統計資訊。

1 EXEC SP_HELPSTATS 'SalesOrderDetail_NoStats', 'ALL'      
了解統計資訊(1/6):密度向量

是的,在估計執行計劃是,SQL Server在productID 列建立了統計資訊來幫助優化器選擇正确的執行計劃。我們來看看這個統計資訊的詳情。

1 DBCC SHOW_STATISTICS('dbo.SalesOrderDetail_NoStats', '_WA_Sys_00000005_7E6CC920')       
了解統計資訊(1/6):密度向量

在統計資訊頭,我們注意到Rows Sampled 值比Rows值小。這是因為在自動建立統計資訊時,SQL Server沒有掃描整個表,隻掃描了表的樣本。為什麼會這樣在接下來的文章裡會談到。簡而言之,在非聚集索引字段裡,統計資訊幫助優化器在每一步操作時判斷估計行數,什麼樣的連接配接是合适的,還有在計劃中的執行順序。 

參考文章:

http://www.sqlservercentral.com/blogs/practicalsqldba/2013/06/25/sql-server-part1-all-about-sql-server-statistics-density-vector/

注:此文章為

WoodyTu

學習MS SQL技術,收集整理相關文檔撰寫,歡迎轉載,請在文章頁面明顯位置給出此文連結!

若您覺得這篇文章還不錯請點選下右下角的推薦,有了您的支援才能激發作者更大的寫作熱情,非常感謝!

繼續閱讀