天天看點

了解統計資訊(2/6):直方圖

在了解統計資訊(1/6):密度向量裡,我們讨論了在統計裡存儲的密度向量資訊。這篇文章會讨論下直方圖。我們再次建立SalesOrderDetail表的副本,并在上面建立2個索引。

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

我們來看看非聚集索引的直方圖資訊。

1 DBCC SHOW_STATISTICS('dbo.SalesOrderDetail', 'ix_productid') WITH HISTOGRAM      
了解統計資訊(2/6):直方圖

你會在輸出裡看到200條記錄,上圖隻顯示了前18條記錄。為了建立直方圖,SQL Server基于索引的第一列值把資料分成不同的桶(步長)。輸出結果裡每條記錄被稱為步長。基于資料分布情況,步長的最大個數是200。直方圖是你資料的統計表述(statistical representation)。換句話說,它是基于索引的第一列值的資料分布情況。直方圖總是基于索引的第一列,即使索引是組合列。這也是為什麼建議把經常被選到的列(most selective column)作為索引的第一列的原因,但也有例外。

我們來看直方圖的輸出結果。它是基于productid值把表裡121317條記錄分成200個桶(步長)。

RANGE_HI_KEY清單示每桶的上邊界值。每桶的下邊界值是上一桶的RANGE_HI_KEY+1。對于第一桶,下邊界值是生成直方圖列的最小值。

RANGE_ROWS清單示在那桶範圍内的記錄數,但不等于RANGE_HI_KEY值。第一條記錄的0值辨別,在整個表裡沒有一條記錄productid值是小于707的。我們來看第11條記錄,它的RANGE_HI_KEY值是718,RANGE_ROWS 列值是218。這就是說,有218條記錄的productid是大于716(上一條RANGE_HI_KEY值)且小于718的。我們可以去驗證下。

1 SELECT COUNT(*) FROM SalesOrderDetail WHERE productid>716 AND productid<718      
了解統計資訊(2/6):直方圖

EQ_ROWS清單示表裡與RANGE_HI_KEY值比對的記錄數。對于第一條記錄,EQ_ROWS值為3083表示表裡productid值為707的記錄有3083條。我們可以驗證下。

1 SELECT COUNT(*) FROM SalesOrderDetail WHERE productid=707      
了解統計資訊(2/6):直方圖

DISTINCT_RANGE_ROWS 清單示在2個RANGE_HI_KEY值之間的不同記錄數(不同productid值)。我們來看第11條的RANGE_HI_KEY值是718,DISTINCT_RANGE_ROWS列值為1,這就是說productid值大于716(上一個RANGE_HI_KEY值)且小于718隻有1條不同記錄。我們可以驗證下。

1 SELECT COUNT(distinct productid) FROM SalesOrderDetail WHERE productid>716 AND productid<718      
了解統計資訊(2/6):直方圖

 AVG_RANGE_ROWS清單示每個不同值的平均記錄數。如果AVG_RANGE_ROWS值大于0的話,和RANGE_ROWS / DISTINCT_RANGE_ROWS相等,不然AVG_RANGE_ROWS的值為1。

SQL Server優化器如何使用直方圖來做基數計算(cardinality estimation )呢?我們看下下面查詢的執行計劃,點選工具欄的

了解統計資訊(2/6):直方圖

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

1 SELECT productid FROM SalesOrderDetail WHERE productid>=716 AND productid<=718       
了解統計資訊(2/6):直方圖

估計行數1513是怎麼計算來的呢?我們看下直方圖。

了解統計資訊(2/6):直方圖

紅色方框裡的數字合計(1076+218+219=1513)就是執行計劃裡估計行數值。

1076是productid值為716的記錄數。

218是productid值大于716且小于718的記錄數。

219是productid值等于718的記錄數。

三個值的彙總就是上述執行計劃裡的估計行數。

當where條件複雜時,優化器會建立稱為列統計的統計資訊,并在直方圖資料上使用複合算法(complex algorithm)進行基數計算(cardinality estimation)。我們在下篇文章會談論這個的更多細節。 

參考文章:

http://www.sqlservercentral.com/blogs/practicalsqldba/2013/06/27/sql-server-part-2-all-about-sql-server-statistics-histogram/

注:此文章為

WoodyTu

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

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

繼續閱讀