《Microsoft Sql server 2008 Internals》读书笔记--第八章The Query Optimizer(5)
?
《Microsoft Sql server 2008 Internals》讀書筆記訂閱地址:
http://www.cnblogs.com/downmoon/category/230397.html/rss
《Microsoft Sql server 2008 Internals》索引目錄:
《Microsoft Sql server 2008 Internal》讀書筆記--目錄索引
上篇主要列舉了統計的概念和統計的設計、統計的濃度。本文將關注篩選統計和字符串統計、基線估計(cardinality estimation)。 ?
?
■篩選統計
作為SQL Server 2008中新增的篩選索引的一部分,篩選統計功能被加入。這意味著(某個基于篩選謂詞的表的行的子集的)統計對象被創建。可以通過sys.stats視圖來查看無數據輸出。篩選統計可以避免一個常見的問題:即由于數據列與列之間的相關性而變得傾斜(不準確)。比如,我們有一個表cars,一列Make,一列Model。如下記錄:
Create?table?Cars(
Car_ID?int?,
Make?nvarchar(20),
MODEL?Nvarchar(20)
);
truncate?table?cars
?
insert?into?Cars
select?1,'Ford','F-150'
union?all?select?2,'Ford','Taurus'
union?all?select?3,'BMW','M3'
假定您想執行如下查詢:
select?*?from?cars?where?Make='Ford'?and?MODEL='F-150'?查詢處理器試圖作選擇時,它假定每一個AND子句的條件是相互獨立的,實際上執行的結果是各條件的乘積,即(1/3)*(2/3)=2/9。然而真實的結果應該是1/3,因為F-150肯定是Ford。當數據量很大時,這個誤差是驚人的。
篩選統計通過捕捉一個帶條件的可能性從Model列進行篩選,篩選條件為Make列為Ford,這在大多數情況下會修正統計中的運算錯誤,特別是在where 子句包含一個相對較小的惟一值時非常有效。
除了假定獨立性外,查詢優化器還采用其他假定來簡化估算進程。另外兩個假定是統一性假定和包含性假定。沒有這些假定,許多常見的查詢將會變得性能寒磣。
■字符串統計
SQL Server 2005采取了一項新內容來改善針對字符串的基線估計,叫做字符串統計或Trie Trees,SQL Server直方圖的上限是200步(或200個惟一值),來存放整個表的分發信息。特別在查詢中使用like時,兩百個惟一值不足以提供(針對字符串的)精準的基線估計,而在表外存儲大量的字符串會占用大量的空間。Trie Tree此時可以用來在列中高效地存儲一些樣例字符串。
Trie Trees沒有公開,但它通常的結構類似于如下:
如果一個列包含如下值:
ABC
AAA
ABCDEF
ADAD
BBB
對應的tier Tree如下:
?SQL Server實際上在列中存儲了一個字符串的樣例。這提供了一種存儲遠超過200的惟一子字符串的頻度信息的能力。
?■基線估計細節
在優化期間,查詢里的每一個運算符被計算以評估該操作影響的行數,這有助于查詢優化器基于不同的查詢計劃作出正確的權衡。這個過程是自下而上的。基表基線和統計被用于輸入到其上的樹節點。我們看一個例子:
Create?table?Table2010_3(col1?int,col2?int,col3?int);go
set?nocount?on
BEGIN?TransAction;
Declare?@i?int
set?@i=0
while?@i<10000
BEGIN
????Insert?into?Table2010_3(col1,col2,col3)?values(@i,@i,@i%50);
????set?@i=@i+1
END
Commit?Transaction
go
Create?statistics?s2010_3?on?Table2010_3(col3);
go
select?col1,col2?from?Table2010_3?where?col3<10
其邏輯查詢樹如下:
對于該查詢,Filter操作請求在每一個參與謂詞的列(本例中是col3)上進行統計,該請求被傳承到Table2010_3,適當的統計對象被創建或更新的地方。統計對象此時被傳遞到篩選器,以決定操作的選擇性。選擇性被用于從樣例延展評估。
一旦一個操作的可選擇性被計算,它與當前查詢的當前行數相乘。
看下圖:
?因為0-49中有10個是小于10的,即10/50=0.2
10000*0.2=2000行。
我們來驗證一下,
本例中,存儲在直方圖中的濃度信息為0.02
又如下列查詢:
?select?COUNT(*)?from?Table2010_3?group?by?col3
評估的行數為(1/0.02)*(10000/10000)=50
當一個多列統計對象被創建時,它按照統計對象的順序為這些被計算的列集計算濃度信息。我們再看下例:
Create?table?Table2010_4(col1?int,col2?int,col3?int);go
set?nocount?on
BEGIN?TransAction;
Declare?@i?int
set?@i=0
while?@i<10000
BEGIN
????Insert?into?Table2010_4(col1,col2,col3)?values(@i%5,@i%10,@i%50);
????set?@i=@i+1
END
Commit?Transaction
go
如果前兩個列是隨機數,則濃度信息可能類似下圖:
這解釋了每個col1,col2,col3的組合實際上是惟一的。通過檢查進入基線估計進程的各種各樣的輸入(Input),判斷計劃在編譯期間有無使用合理的信息成為可能。
本文主要介紹了篩選統計和字符串統計、基線估計,下文將關注Limitation和Costing
?
總結
以上是生活随笔為你收集整理的《Microsoft Sql server 2008 Internals》读书笔记--第八章The Query Optimizer(5)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 学习Unix/Linux编程要学些什么
- 下一篇: HTML5 应用的现状与前景