歡迎回到性能調(diào)優(yōu)培訓(xùn)。今天我想詳細(xì)談下統(tǒng)計信息在SQL Server內(nèi)部是如何呈現(xiàn)的。假設(shè)有這樣的問題:執(zhí)行計劃里的某個運算符的估計行數(shù)是42,但你知道對于這個查詢,42不是正確的答案。但是你怎么來解讀統(tǒng)計信息來理解這個估計是從哪里來的?我們來談?wù)撓轮狈綀D(Histogram)和密度向量(Density Vector)。
直方圖(Histogram)首先我們來看下直方圖。直方圖的用途是用高效、壓縮的方式存儲列數(shù)據(jù)分布情況。每次當(dāng)你在表上創(chuàng)建索引時(聚集/非聚集索引),SQL Server會為你自動創(chuàng)建統(tǒng)計信息。這個統(tǒng)計信息就包含了那列(索引鍵)的數(shù)據(jù)分布信息。比如你有一個訂單表,里面有個Country列,這列里有很多國家名字。因此直方圖就是對這些國家個數(shù)分布情況的可視化:
在直方圖里,我們用很多柱條描述數(shù)據(jù)分布情況:柱條越高,那列的這個值就記錄數(shù)就越多。SQL Server使用同樣的概念和格式來描述數(shù)據(jù)分布情況。我們通過一個例子來詳細(xì)了解下。在AdventureWorks2008R2數(shù)據(jù)庫里,我們找到表SalesOrderDetail里的PRoductID列。這ProductID列存儲著具體的銷售產(chǎn)品ID信息。可以看到,ProductID列也有索引定義,那就說有對應(yīng)的統(tǒng)計信息來描述ProductID列的數(shù)據(jù)分布情況。
在SSMS里,你通過查看表屬性來查看列和統(tǒng)計信息,也可以使用DBCC SHOW_STATISTICS命令在結(jié)果里輸出統(tǒng)計信息。
1 -- Show the statistics for a given index2 DBCC SHOW_STATISTICS ('Sales.SalesOrderDetail', IX_SalesOrderDetail_ProductID)3 GO
從上圖可以看到,這個命令返回3個不同的記錄集:
如果你想詳細(xì)了解這部分的統(tǒng)計信息是如何用來做基數(shù)預(yù)估的,可以看下統(tǒng)計信息內(nèi)幕:直方圖和密度向量。
密度向量(Density Vector)我們再來看看神秘的密度向量,看下非聚集索引IX_SalesOrderDetail_ProductID,這個索引只在ProductID列建立。但是每個非聚集索引,SQL Server在索引的頁層也保存聚集鍵作為邏輯指針。當(dāng)你定義了非唯一的非聚集索引,聚集鍵也是非聚集索引導(dǎo)航結(jié)構(gòu)的一部分。表里的聚集鍵SalesOrderID是個組合列,包含SalesOrderID列和SalesOrderDetailID列。
這就是說我們的非唯一非聚集索引事實上包含ProductID,SalesOrderID和SalesOrderDetailID列。索引鍵是個組合鍵。同樣SQL Server需要為其他列創(chuàng)建密度向量,因為只有第1列(ProductID)是直方圖里有信息,這個在上一部分我們已經(jīng)看過了。當(dāng)你看用DBCC SHOW_STATISTICS命令的輸出時,密度向量是第2個表信息。
SQL Server在這里存儲選擇率(selectivity),不同列組合的密度。例如,ProductID列的All density值是0.003759399,你可以用下列語句來驗證下:
1 -- The "All Density" value for the column ProductID: 0,00375939849624060152 SELECT 1 / CAST(COUNT(DISTINCT ProductID) AS NUMERIC(18, 2)) FROM Sales.SalesOrderDetail3 GO
對于ProductID,SalesOrderID組合列和ProductID,SalesOrderID,SalesOrderDetailID組合列的All density值分別是8.242868E-06和8.242868E-06。你可以用1除以2個組合列的唯一值來驗證下。這里我們的記錄是121317,這些聚集值(SalesOrderID,SalesOrderDetailID組成了聚集鍵)都是唯一的,我們可以計算下:1/121317=8.242867858585359e-6。
在基數(shù)預(yù)估期間,SQL Server如何使用這個信息,詳細(xì)可以點擊剛才提到的統(tǒng)計信息內(nèi)幕:直方圖和密度向量。
小結(jié)今天你看到SQL Server內(nèi)部是如何構(gòu)建統(tǒng)計信息的。這里最重要的是直方圖(Histogram)和密度向量(Density Vector),它們一直是用來做基數(shù)預(yù)估的。希望這次性能調(diào)優(yōu)培訓(xùn)你有所收獲。
你可以閱讀下面文章,加深對統(tǒng)計信息的理解:
理解統(tǒng)計信息(1/6):密度向量
理解統(tǒng)計信息(2/6):直方圖
理解統(tǒng)計信息(3/6):誰創(chuàng)建和管理統(tǒng)計信息?在性能調(diào)優(yōu)中,統(tǒng)計信息的作用
理解統(tǒng)計信息(4/6):自動更新統(tǒng)計信息的閥值——人為更新統(tǒng)計信息的重要性
理解統(tǒng)計信息(5/6):如何檢測過期的統(tǒng)計信息
理解統(tǒng)計信息(6/6):統(tǒng)計信息匯總貼
統(tǒng)計信息內(nèi)幕:直方圖和密度向量
下周我們繼續(xù)討論在SQL Server里使用基數(shù)預(yù)估(cardinality estimation)的局限性,還有如何解決它們。到時候見!
新聞熱點
疑難解答
圖片精選