成人性生交大片免费看视频r_亚洲综合极品香蕉久久网_在线视频免费观看一区_亚洲精品亚洲人成人网在线播放_国产精品毛片av_久久久久国产精品www_亚洲国产一区二区三区在线播_日韩一区二区三区四区区区_亚洲精品国产无套在线观_国产免费www

主頁 > 知識庫 > 深入分析SqlServer查詢計劃

深入分析SqlServer查詢計劃

熱門標(biāo)簽:洛陽外呼系統(tǒng)平臺 電銷機(jī)器人被曝光 地圖標(biāo)注一個圓圈怎么用 寧波人工外呼系統(tǒng)有效果嗎 真人語音電銷機(jī)器人 400外呼系統(tǒng)合法 如何在地圖標(biāo)注自己店鋪 怎樣把地圖標(biāo)注導(dǎo)入公司地址 廣州人工電銷機(jī)器人費(fèi)用

對于SQL Server的優(yōu)化來說,優(yōu)化查詢可能是很常見的事情。由于數(shù)據(jù)庫的優(yōu)化,本身也是一個涉及面比較的廣的話題, 因此本文只談優(yōu)化查詢時如何看懂SQL Server查詢計劃。畢竟我對SQL Server的認(rèn)識有限,如有錯誤,也懇請您在發(fā)現(xiàn)后及時批評指正。

首先,打開【SQL Server Management Studio】,輸入一個查詢語句看看SQL Server是如何顯示查詢計劃的吧。
說明:本文所演示的數(shù)據(jù)庫,是我為一個演示程序?qū)S脺?zhǔn)備的數(shù)據(jù)庫,可以在此網(wǎng)頁中下載。

select v.OrderID, v.CustomerID, v.CustomerName, v.OrderDate, v.SumMoney, v.Finished
from  OrdersView as v
where v.OrderDate >= '2010-12-1' and v.OrderDate  '2011-12-1';

其中,OrdersView是一個視圖,其定義如下:

SELECT   dbo.Orders.OrderID, dbo.Orders.CustomerID, dbo.Orders.OrderDate, 
      dbo.Orders.SumMoney, dbo.Orders.Finished, 
      ISNULL(dbo.Customers.CustomerName, N'') AS CustomerName
FROM     dbo.Orders LEFT OUTER JOIN
        dbo.Customers ON dbo.Orders.CustomerID = dbo.Customers.CustomerID

對于前一句查詢,SQL Server給出的查詢計劃如下(點(diǎn)擊工具欄上的【顯示估計的執(zhí)行計劃】按鈕):

從這個圖中,我們至少可以得到3個有用的信息:

1. 哪些執(zhí)行步驟花費(fèi)的成本比較高。顯然,最右邊的二個步驟的成本是比較高的。
2. 哪些執(zhí)行步驟產(chǎn)生的數(shù)據(jù)量比較多。對于每個步驟所產(chǎn)生的數(shù)據(jù)量, SQL Server的執(zhí)行計劃是用【線條粗細(xì)】來表示的,因此也很容易地從分辨出來。
3. 每一步執(zhí)行了什么樣的動作。

對于一個比較慢的查詢來說,我們通常要知道哪些步驟的成本比較高,進(jìn)而,可以嘗試一些改進(jìn)的方法。 一般來說,如果您不能通過:提高硬件性能或者調(diào)整OS,SQL Server的設(shè)置之類的方式來解決問題,那么剩下的可選方法通常也只有以下這些了:

1. 為【scan】這類操作增加相應(yīng)字段的索引。
2. 有時重建索引或許也是有效的,具體情形請參考后文。
3. 調(diào)整語句結(jié)構(gòu),引導(dǎo)SQL Server采用其它的查詢方案去執(zhí)行。
4. 調(diào)整表結(jié)構(gòu)(分表或者分區(qū))。

下面再來說說一些很重要的理論知識,這些內(nèi)容對于執(zhí)行計劃的理解是很有幫助的。

回到頂部SQL Server 查找記錄的方法

說到這里,不得不說SQL Server的索引了。SQL Server有二種索引:聚集索引和非聚集索引。二者的差別在于:【聚集索引】直接決定了記錄的存放位置, 或者說:根據(jù)聚集索引可以直接獲取到記錄?!痉蔷奂饕勘4媪硕€信息:1.相應(yīng)索引字段的值,2.記錄對應(yīng)聚集索引的位置(如果表沒有聚集索引則保存記錄指針)。 因此,如果能通過【聚集索引】來查找記錄,顯然也是最快的。

SQL Server 會有以下方法來查找您需要的數(shù)據(jù)記錄:

1. 【Table Scan】:遍歷整個表,查找所有匹配的記錄行。這個操作將會一行一行的檢查,當(dāng)然,效率也是最差的。
2. 【Index Scan】:根據(jù)索引,從表中過濾出來一部分記錄,再查找所有匹配的記錄行,顯然比第一種方式的查找范圍要小,因此比【Table Scan】要快。
3. 【Index Seek】:根據(jù)索引,定位(獲取)記錄的存放位置,然后取得記錄,因此,比起前二種方式會更快。
4. 【Clustered Index Scan】:和【Table Scan】一樣。注意:不要以為這里有個Index,就認(rèn)為不一樣了。 其實(shí)它的意思是說:按聚集索引來逐行掃描每一行記錄,因為記錄就是按聚集索引來順序存放的。 而【Table Scan】只是說:要掃描的表沒有聚集索引而已,因此這二個操作本質(zhì)上也是一樣的。
5. 【Clustered Index Seek】:直接根據(jù)聚集索引獲取記錄,最快!

所以,當(dāng)發(fā)現(xiàn)某個查詢比較慢時,可以首先檢查哪些操作的成本比較高,再看看那些操作在查找記錄時, 是不是【Table Scan】或者【Clustered Index Scan】,如果確實(shí)和這二種操作類型有關(guān),則要考慮增加索引來解決了。 不過,增加索引后,也會影響數(shù)據(jù)表的修改動作,因為修改數(shù)據(jù)表時,要更新相應(yīng)字段的索引。所以索引過多,也會影響性能。 還有一種情況是不適合增加索引的:某個字段用0或1表示的狀態(tài)。例如可能有絕大多數(shù)是1,那么此時加索引根本就沒有意義。 這時只能考慮為0或者1這二種情況分開來保存了,分表或者分區(qū)都是不錯的選擇。

如果不能通過增加索引和調(diào)整表來解決,那么可以試試調(diào)整語句結(jié)構(gòu),引導(dǎo)SQL Server采用其它的查詢方案去執(zhí)行。 這種方法要求: 1.對語句所要完成的功能很清楚, 2.對要查詢的數(shù)據(jù)表結(jié)構(gòu)很清楚, 3.對相關(guān)的業(yè)務(wù)背景知識很清楚。 如果能通過這種方法去解決,當(dāng)然也是很好的解決方法了。不過,有時SQL Server比較智能,即使你調(diào)整語句結(jié)構(gòu),也不會影響它的執(zhí)行計劃。

如何比較二個相同功能的SQL語句的性能好壞呢,我建議采用二種方法: 1. 直接把二個查詢語句放在【SQL Server Management Studio】,然后去看它們的【執(zhí)行計劃】,SQL Server會以百分比的方式告訴你二個查詢的【查詢開銷】。 這種方法簡單,通常也是可以參考的,不過,有時也會不準(zhǔn),具體原因請接著往下看(可能索引統(tǒng)計信息過舊)。
2. 根據(jù)真實(shí)的程序調(diào)用,寫相應(yīng)的測試代碼去調(diào)用:這種方法就麻煩一些,但是它更能代表現(xiàn)實(shí)調(diào)用情況, 得到的結(jié)果也是更具有參考價值的,因此也是值得的。

回到頂部SQL Server Join 方式

在SQL Server中,每個join命令,都會在內(nèi)部執(zhí)行時采用三種更具體的方式來運(yùn)行:

1. 【Nested Loops join】,如果一個聯(lián)接輸入很小,而另一個聯(lián)接輸入很大而且已在其聯(lián)接列上創(chuàng)建了索引, 則索引 Nested Loops 連接是最快的聯(lián)接操作,因為它們需要的 I/O 和比較都最少。

嵌套循環(huán)聯(lián)接也稱為“嵌套迭代”,它將一個聯(lián)接輸入用作外部輸入表(顯示為圖形執(zhí)行計劃中的頂端輸入),將另一個聯(lián)接輸入用作內(nèi)部(底端)輸入表。外部循環(huán)逐行處理外部輸入表。內(nèi)部循環(huán)會針對每個外部行執(zhí)行,在內(nèi)部輸入表中搜索匹配行??梢杂孟旅娴膫未a來理解:

foreach(row r1 in outer table)
  foreach(row r2 in inner table)
    if( r1, r2 符合匹配條件 )
      output(r1, r2);

最簡單的情況是,搜索時掃描整個表或索引;這稱為“單純嵌套循環(huán)聯(lián)接”。如果搜索時使用索引,則稱為“索引嵌套循環(huán)聯(lián)接”。如果將索引生成為查詢計劃的一部分(并在查詢完成后立即將索引破壞),則稱為“臨時索引嵌套循環(huán)聯(lián)接”。查詢優(yōu)化器考慮了所有這些不同情況。

如果外部輸入較小而內(nèi)部輸入較大且預(yù)先創(chuàng)建了索引,則嵌套循環(huán)聯(lián)接尤其有效。在許多小事務(wù)中(如那些只影響較小的一組行的事務(wù)),索引嵌套循環(huán)聯(lián)接優(yōu)于合并聯(lián)接和哈希聯(lián)接。但在大型查詢中,嵌套循環(huán)聯(lián)接通常不是最佳選擇。

2. 【Merge Join】,如果兩個聯(lián)接輸入并不小但已在二者聯(lián)接列上排序(例如,如果它們是通過掃描已排序的索引獲得的),則合并聯(lián)接是最快的聯(lián)接操作。如果兩個聯(lián)接輸入都很大,而且這兩個輸入的大小差不多,則預(yù)先排序的合并聯(lián)接提供的性能與哈希聯(lián)接相近。但是,如果這兩個輸入的大小相差很大,則哈希聯(lián)接操作通??斓枚?。

合并聯(lián)接要求兩個輸入都在合并列上排序,而合并列由聯(lián)接謂詞的等效 (ON) 子句定義。通常,查詢優(yōu)化器掃描索引(如果在適當(dāng)?shù)囊唤M列上存在索引),或在合并聯(lián)接的下面放一個排序運(yùn)算符。在極少數(shù)情況下,雖然可能有多個等效子句,但只用其中一些可用的等效子句獲得合并列。

由于每個輸入都已排序,因此 Merge Join 運(yùn)算符將從每個輸入獲取一行并將其進(jìn)行比較。例如,對于內(nèi)聯(lián)接操作,如果行相等則返回。如果行不相等,則廢棄值較小的行并從該輸入獲得另一行。這一過程將重復(fù)進(jìn)行,直到處理完所有的行為止。

合并聯(lián)接操作可以是常規(guī)操作,也可以是多對多操作。多對多合并聯(lián)接使用臨時表存儲行(會影響效率)。如果每個輸入中有重復(fù)值,則在處理其中一個輸入中的每個重復(fù)項時,另一個輸入必須重繞到重復(fù)項的開始位置。 可以創(chuàng)建唯一索引告訴SQL Server不會有重復(fù)值。

如果存在駐留謂詞,則所有滿足合并謂詞的行都將對該駐留謂詞取值,而只返回那些滿足該駐留謂詞的行。

合并聯(lián)接本身的速度很快,但如果需要排序操作,選擇合并聯(lián)接就會非常費(fèi)時。然而,如果數(shù)據(jù)量很大且能夠從現(xiàn)有 B 樹索引中獲得預(yù)排序的所需數(shù)據(jù),則合并聯(lián)接通常是最快的可用聯(lián)接算法。

3. 【Hash Join】,哈希聯(lián)接可以有效處理未排序的大型非索引輸入。它們對復(fù)雜查詢的中間結(jié)果很有用,因為: 1. 中間結(jié)果未經(jīng)索引(除非已經(jīng)顯式保存到磁盤上然后創(chuàng)建索引),而且通常不為查詢計劃中的下一個操作進(jìn)行適當(dāng)?shù)呐判颉?2. 查詢優(yōu)化器只估計中間結(jié)果的大小。由于對于復(fù)雜查詢,估計可能有很大的誤差,因此如果中間結(jié)果比預(yù)期的大得多,則處理中間結(jié)果的算法不僅必須有效而且必須適度弱化。

哈希聯(lián)接可以減少使用非規(guī)范化。非規(guī)范化一般通過減少聯(lián)接操作獲得更好的性能,盡管這樣做有冗余之險(如不一致的更新)。哈希聯(lián)接則減少使用非規(guī)范化的需要。哈希聯(lián)接使垂直分區(qū)(用單獨(dú)的文件或索引代表單個表中的幾組列)得以成為物理數(shù)據(jù)庫設(shè)計的可行選項。

哈希聯(lián)接有兩種輸入:生成輸入和探測輸入。查詢優(yōu)化器指派這些角色,使兩個輸入中較小的那個作為生成輸入。

哈希聯(lián)接用于多種設(shè)置匹配操作:內(nèi)部聯(lián)接;左外部聯(lián)接、右外部聯(lián)接和完全外部聯(lián)接;左半聯(lián)接和右半聯(lián)接;交集;聯(lián)合和差異。此外,哈希聯(lián)接的某種變形可以進(jìn)行重復(fù)刪除和分組,例如 SUM(salary) GROUP BY department。這些修改對生成和探測角色只使用一個輸入。

哈希聯(lián)接又分為3個類型:內(nèi)存中的哈希聯(lián)接、Grace 哈希聯(lián)接和遞歸哈希聯(lián)接。

內(nèi)存中的哈希聯(lián)接:哈希聯(lián)接先掃描或計算整個生成輸入,然后在內(nèi)存中生成哈希表。根據(jù)計算得出的哈希鍵的哈希值,將每行插入哈希存儲桶。如果整個生成輸入小于可用內(nèi)存,則可以將所有行都插入哈希表中。生成階段之后是探測階段。一次一行地對整個探測輸入進(jìn)行掃描或計算,并為每個探測行計算哈希鍵的值,掃描相應(yīng)的哈希存儲桶并生成匹配項。

Grace 哈希聯(lián)接:如果生成輸入大于內(nèi)存,哈希聯(lián)接將分為幾步進(jìn)行。這稱為“Grace 哈希聯(lián)接”。每一步都分為生成階段和探測階段。首先,消耗整個生成和探測輸入并將其分區(qū)(使用哈希鍵上的哈希函數(shù))為多個文件。對哈希鍵使用哈希函數(shù)可以保證任意兩個聯(lián)接記錄一定位于相同的文件對中。因此,聯(lián)接兩個大輸入的任務(wù)簡化為相同任務(wù)的多個較小的實(shí)例。然后將哈希聯(lián)接應(yīng)用于每對分區(qū)文件。

遞歸哈希聯(lián)接:如果生成輸入非常大,以至于標(biāo)準(zhǔn)外部合并的輸入需要多個合并級別,則需要多個分區(qū)步驟和多個分區(qū)級別。如果只有某些分區(qū)較大,則只需對那些分區(qū)使用附加的分區(qū)步驟。為了使所有分區(qū)步驟盡可能快,將使用大的異步 I/O 操作以便單個線程就能使多個磁盤驅(qū)動器繁忙工作。

在優(yōu)化過程中不能始終確定使用哪種哈希聯(lián)接。因此,SQL Server 開始時使用內(nèi)存中的哈希聯(lián)接,然后根據(jù)生成輸入的大小逐漸轉(zhuǎn)換到 Grace 哈希聯(lián)接和遞歸哈希聯(lián)接。
如果優(yōu)化器錯誤地預(yù)計兩個輸入中哪個較小并由此確定哪個作為生成輸入,生成角色和探測角色將動態(tài)反轉(zhuǎn)。哈希聯(lián)接確保使用較小的溢出文件作為生成輸入。這一技術(shù)稱為“角色反轉(zhuǎn)”。至少一個文件溢出到磁盤后,哈希聯(lián)接中才會發(fā)生角色反轉(zhuǎn)。

說明:您也可以顯式的指定聯(lián)接方式,SQL Server會盡量尊重您的選擇。比如你可以這樣寫:inner loop join, left outer merge join, inner hash join
但是,我還是建議您不要這樣做,因為SQL Server的選擇基本上都是正確的,不信您可以試一下。

好了,說了一大堆理論東西,再來個實(shí)際的例子解釋一下吧。

回到頂部更具體執(zhí)行過程

前面,我給出一張圖片,它反映了SQL Server在執(zhí)行某個查詢的執(zhí)行計劃,但它反映的信息可能不太細(xì)致,當(dāng)然,您可以把鼠標(biāo)指標(biāo)移動某個節(jié)點(diǎn)上,會有以下信息出現(xiàn):

剛好,我裝的是中文版的,上面都是漢字,我也不多說了。我要說的是另一種方式的執(zhí)行過程,比這個包含更多的執(zhí)行信息, 而且是實(shí)際的執(zhí)行情況。(當(dāng)然,您也可以繼續(xù)使用圖形方式,在運(yùn)行查詢前點(diǎn)擊工具欄上的【包括實(shí)際的執(zhí)行計劃】按鈕)

讓我們再次回到【SQL Server Management Studio】,輸入以下語句,然后執(zhí)行。

set statistics profile on 

select v.OrderID, v.CustomerID, v.CustomerName, v.OrderDate, v.SumMoney, v.Finished
from  OrdersView as v
where v.OrderDate >= '2010-12-1' and v.OrderDate  '2011-12-1';

注意:現(xiàn)在加了一句,【set statistics profile on 】,得到的結(jié)果如下:

可以從圖片上看到,執(zhí)行查詢后,得到二個表格,上面的表格顯示了查詢的結(jié)果,下面的表格顯示了查詢的執(zhí)行過程。相比本文的第一張圖片, 這張圖片可能在直觀上不太友好,但是,它能反映更多的信息,而且尤其在比較復(fù)雜的查詢時,可能看起來更容易,因為對于復(fù)雜的查詢,【執(zhí)行計劃】的步驟太多,圖形方式會造成圖形過大,不容易觀察。 而且這張執(zhí)行過程表格能反映2個很有價值的數(shù)據(jù)(前二列)。

還是來看看這個【執(zhí)行過程表格】吧。我來挑幾個重要的說一下。
【Rows】:表示在一個執(zhí)行步驟中,所產(chǎn)生的記錄條數(shù)。(真實(shí)數(shù)據(jù),非預(yù)期)
【Executes】:表示某個執(zhí)行步驟被執(zhí)行的次數(shù)。(真實(shí)數(shù)據(jù),非預(yù)期)
【Stmt Text】:表示要執(zhí)行的步驟的描述。
【EstimateRows】:表示要預(yù)期返回多少行數(shù)據(jù)。

在這個【執(zhí)行過程表格】中,對于優(yōu)化查詢來說,我認(rèn)為前三列是比較重要的。對于前二列,我上面也解釋了,意思也很清楚。 前二列的數(shù)字也大致反映了那些步驟所花的成本,對于比較慢的查詢中,應(yīng)該留意它們。 【Stmt Text】會告訴你每個步驟做了什么事情。對于這種表格,它所要表達(dá)的其實(shí)是一種樹型信息(一行就表示在圖形方式下的一個節(jié)點(diǎn)), 所以,我建議從最內(nèi)層開始去讀它們。做為示例,我來解釋一下這張表格它所表達(dá)的執(zhí)行過程。

第5行:【Clustered Index Seek(OBJECT:([MyNorthwind].[dbo].[Customers].[PK_Customers]), SEEK:([MyNorthwind].[dbo].[Customers].[CustomerID]=[MyNorthwind].[dbo].[Orders].[CustomerID]) ORDERED FORWARD)】, 意思是說,SQL Server在對表Customers做Seek操作,而且是按照【Clustered Index Seek】的方式,對應(yīng)的索引是【PK_Customers】,seek的值來源于[Orders].[CustomerID]

第4行:【Clustered Index Scan(OBJECT:([MyNorthwind].[dbo].[Orders].[PK_Orders]), WHERE:([MyNorthwind].[dbo].[Orders].[OrderDate]>='2010-12-01 00:00:00.000' AND [MyNorthwind].[dbo].[Orders].[OrderDate]'2011-12-01 00:00:00.000'))】, 意思是說,SQL Server在對表Customers做Scan操作,即:最差的【表掃描】的方式,原因是,OrderDate列上沒有索引,所以只能這樣了。

第3行:【Nested Loops(Left Outer Join, OUTER REFERENCES:([MyNorthwind].[dbo].[Orders].[CustomerID]))】, 意思是說,SQL Server把第5行和第4行產(chǎn)生的數(shù)據(jù)用【Nested Loops】的方式聯(lián)接起來,其中Outer表是Orders,要聯(lián)接的匹配操作也在第5行中指出了。

第2行:【Compute Scalar(DEFINE:([Expr1006]=isnull([MyNorthwind].[dbo].[Customers].[CustomerName],N'')))】, 意思是說,要執(zhí)行一個isnull()函數(shù)的調(diào)用。具體原因請參考本文前部分中給出視圖定義代碼。

第1行:【SELECT [v].[OrderID],[v].[CustomerID],[v].[CustomerName],[v].[OrderDate],[v].[SumMoney],[v].[Finished] FROM [OrdersView] [v] WHERE [v].[OrderDate]>=@1 AND [v].[OrderDate]@2】, 通常第1行就是整個查詢,表示它的返回值。

回到頂部索引統(tǒng)計信息:查詢計劃的選擇依據(jù)

前面一直說到【執(zhí)行計劃】,既然是計劃,就表示要在具體執(zhí)行前就能確定下來的操作方案。那么SQL Server是如何選擇一個執(zhí)行計劃的呢? SQL Server怎么知道什么時候該用索引或者用哪個索引呢? 對于SQL Server來說,每當(dāng)要執(zhí)行一個查詢時,都要首先檢查這個查詢的執(zhí)行計劃是否存在緩存中,如果沒有,就要生成一個執(zhí)行計劃, 具體在產(chǎn)生執(zhí)行計劃時,并不是看有哪些索引可用(隨機(jī)選擇),而是會參考一種被稱為【索引統(tǒng)計信息】的數(shù)據(jù)。 如果您仔細(xì)地看一下前面的執(zhí)行計劃或者執(zhí)行過程表格,會發(fā)現(xiàn)SQL Server能預(yù)估每個步驟所產(chǎn)生的數(shù)據(jù)量, 正是因為SQL Server能預(yù)估這些數(shù)據(jù)量,SQL Server才能選擇一個它認(rèn)為最合適的方法去執(zhí)行查詢過程, 此時【索引統(tǒng)計信息】就能告訴SQL Server這些信息。 說到這里,您是不是有點(diǎn)好奇呢,為了讓您對【索引統(tǒng)計信息】有個感性的認(rèn)識,我們來看看【索引統(tǒng)計信息】是個什么樣子的。 請在【SQL Server Management Studio】,輸入以下語句,然后執(zhí)行。

dbcc show_statistics (Products, IX_CategoryID)

得到的結(jié)果如下圖:

首先,還是解釋一下命令:【dbcc show_statistics】這個命令可以顯示我們想知道的【索引統(tǒng)計信息】,它需要二個參數(shù),1. 表名,2. 索引名

再來看看命令的結(jié)果,它有三個表格組成:
1. 第一個表格,它列出了這個索引統(tǒng)計信息的主要信息。

列名 說明Name統(tǒng)計信息的名稱。Updated上一次更新統(tǒng)計信息的日期和時間。Rows表中的行數(shù)。Rows Sampled統(tǒng)計信息的抽樣行數(shù)。Steps數(shù)據(jù)可分成多少個組,與第三個表對應(yīng)。Density第一個索引列前綴的選擇性(不包括 EQ_ROWS)。Average key length所有索引列的平均長度。String Index如果為“是”,則統(tǒng)計信息中包含字符串摘要索引,以支持為 LIKE 條件估算結(jié)果集大小。僅適用于char、varchar、nchar和nvarchar、varchar(max)、nvarchar(max)、text以及ntext數(shù)據(jù)類型的前導(dǎo)列。

2. 第二個表格,它列出各種字段組合的選擇性,數(shù)據(jù)越小表示重復(fù)越性越小,當(dāng)然選擇性也就越高。

列名 說明All density索引列前綴集的選擇性(包括 EQ_ROWS)。注意:這個值越小就表示選擇性越高。
如果這個值小于0.1,這個索引的選擇性就比較高,反之,則表示選擇性就不高了。Average length索引列前綴集的平均長度。Columns為其顯示All density和Average length的索引列前綴的名稱。

3. 第三個表格,數(shù)據(jù)分布的直方圖,SQL Server就是靠它預(yù)估一些執(zhí)行步驟的數(shù)據(jù)量。

列名 說明RANGE_HI_KEY每個組中的最大值。RANGE_ROWS每組數(shù)據(jù)組的估算行數(shù),不包含最大值。EQ_ROWS每組數(shù)據(jù)組中與最大值相等的行的估算數(shù)目。DISTINCT_RANGE_ROWS每組數(shù)據(jù)組中的非重復(fù)值的估算數(shù)目,不包含最大值。AVG_RANGE_ROWS每組數(shù)據(jù)組中的重復(fù)值的平均數(shù)目,不包含最大值,計算公式:RANGE_ROWS / DISTINCT_RANGE_ROWS for DISTINCT_RANGE_ROWS > 0

為了能讓您更好的理解這些數(shù)據(jù),尤其是第三組,請看下圖:

當(dāng)時我在填充測試數(shù)據(jù)時,故意把CategoryId分為1到8(10是后來臨時加的),每組填充了78條數(shù)據(jù)。所以【索引統(tǒng)計信息】的第三個表格的數(shù)據(jù)也都是正確的, 也正是根據(jù)這些統(tǒng)計信息,SQL Server才能對每個執(zhí)行步驟預(yù)估相應(yīng)的數(shù)據(jù)量,從而影響Join之類的選擇。當(dāng)然了,在選擇Join方式時, 也要參考第二個表格中字段的選擇性。SQL Server在為查詢生成執(zhí)行計劃時, 查詢優(yōu)化器將使用這些統(tǒng)計信息并結(jié)合相關(guān)的索引來評估每種方案的開銷來選擇最佳的查詢計劃。

再來個例子說明一下統(tǒng)計信息對于查詢計劃的重要性。首先多加點(diǎn)數(shù)據(jù),請看以下代碼:

declare @newCategoryId int;
insert into dbo.Categories (CategoryName) values(N'Test statistics');
set @newCategoryId = scope_identity();

declare @count int;
set @count = 0;

while( @count  100000 )
begin
  insert into Products (ProductName, CategoryID, Unit, UnitPrice, Quantity, Remark) 
  values( cast(newid() as nvarchar(50)), @newCategoryId, N'個', 100, @count +1, N'');

  set @count = @count + 1;
end
go

update statistics Products;
go

再來看看索引統(tǒng)計信息:

再來看看同一個查詢,但因為查詢參數(shù)值不同時,SQL Server選擇的執(zhí)行計劃:

select p.ProductId, t.Quantity 
from Products as p left outer join [Order Details] as t on p.ProductId = t.ProductId 
where p.CategoryId = 26;  -- 26 就是最新產(chǎn)生的CategoryId,因此這個查詢會返回10W條記錄

select p.ProductId, t.Quantity 
from Products as p left outer join [Order Details] as t on p.ProductId = t.ProductId 
where p.CategoryId = 6;  -- 這個查詢會返回95條記錄

從上圖可以看出,由于CategoryId的參數(shù)值不同,SQL Server會選擇完全不同的執(zhí)行計劃。統(tǒng)計信息重要性在這里體現(xiàn)的很清楚吧。

創(chuàng)建統(tǒng)計信息后,數(shù)據(jù)庫引擎對列值(根據(jù)這些值創(chuàng)建統(tǒng)計信息)進(jìn)行排序, 并根據(jù)這些值(最多 200 個,按間隔分隔開)創(chuàng)建一個“直方圖”。直方圖指定有多少行精確匹配每個間隔值, 有多少行在間隔范圍內(nèi),以及間隔中值的密度大小或重復(fù)值的發(fā)生率。

SQL Server 2005 引入了對 char、varchar、varchar(max)、nchar、nvarchar、nvarchar(max)、text 和 ntext 列創(chuàng)建的統(tǒng)計信息收集的其他信息。這些信息稱為“字符串摘要”,可以幫助查詢優(yōu)化器估計字符串模式中查詢謂詞的選擇性。 查詢中有 LIKE 條件時,使用字符串摘要可以更準(zhǔn)確地估計結(jié)果集大小,并不斷優(yōu)化查詢計劃。 這些條件包括諸如 WHERE ProductName LIKE '%Bike' 和 WHERE Name LIKE '[CS]heryl' 之類的條件。

既然【索引統(tǒng)計信息】這么重要,那么它會在什么時候生成或者更新呢?事實(shí)上,【索引統(tǒng)計信息】是不用我們手工去維護(hù)的, SQL Server會自動去維護(hù)它們。而且在SQL Server中也有個參數(shù)來控制這個更新方式:

統(tǒng)計信息自動功能工作方式

創(chuàng)建索引時,查詢優(yōu)化器自動存儲有關(guān)索引列的統(tǒng)計信息。另外,當(dāng) AUTO_CREATE_STATISTICS 數(shù)據(jù)庫選項設(shè)置為 ON(默認(rèn)值)時, 數(shù)據(jù)庫引擎自動為沒有用于謂詞的索引的列創(chuàng)建統(tǒng)計信息。

隨著列中數(shù)據(jù)發(fā)生變化,索引和列的統(tǒng)計信息可能會過時,從而導(dǎo)致查詢優(yōu)化器選擇的查詢處理方法不是最佳的。 例如,如果創(chuàng)建一個包含一個索引列和 1,000 行數(shù)據(jù)的表,每一行在索引列中的值都是唯一的, 則查詢優(yōu)化器將把該索引列視為收集查詢數(shù)據(jù)的好方法。如果更新列中的數(shù)據(jù)后存在許多重復(fù)值, 則該列不再是用于查詢的理想候選列。但是,查詢優(yōu)化器仍然根據(jù)索引的過時分布統(tǒng)計信息(基于更新前的數(shù)據(jù)),將其視為好的候選列。

當(dāng) AUTO_UPDATE_STATISTICS 數(shù)據(jù)庫選項設(shè)置為 ON(默認(rèn)值)時,查詢優(yōu)化器會在表中的數(shù)據(jù)發(fā)生變化時自動定期更新這些統(tǒng)計信息。 每當(dāng)查詢執(zhí)行計劃中使用的統(tǒng)計信息沒有通過針對當(dāng)前統(tǒng)計信息的測試時就會啟動統(tǒng)計信息更新。 采樣是在各個數(shù)據(jù)頁上隨機(jī)進(jìn)行的,取自表或統(tǒng)計信息所需列的最小非聚集索引。 從磁盤讀取一個數(shù)據(jù)頁后,該數(shù)據(jù)頁上的所有行都被用來更新統(tǒng)計信息。 常規(guī)情況是:在大約有 20% 的數(shù)據(jù)行發(fā)生變化時更新統(tǒng)計信息。但是,查詢優(yōu)化器始終確保采樣的行數(shù)盡量少。 對于小于 8 MB 的表,則始終進(jìn)行完整掃描來收集統(tǒng)計信息。

采樣數(shù)據(jù)(而不是分析所有數(shù)據(jù))可以將統(tǒng)計信息自動更新的開銷降至最低。 在某些情況下,統(tǒng)計采樣無法獲得表中數(shù)據(jù)的精確特征。可以使用 UPDATE STATISTICS 語句的 SAMPLE 子句和 FULLSCAN 子句, 控制按逐個表的方式手動更新統(tǒng)計信息時采樣的數(shù)據(jù)量。FULLSCAN 子句指定掃描表中的所有數(shù)據(jù)來收集統(tǒng)計信息, 而 SAMPLE 子句用來指定采樣的行數(shù)百分比或采樣的行數(shù)

在 SQL Server 2005 中,數(shù)據(jù)庫選項 AUTO_UPDATE_STATISTICS_ASYNC 提供了統(tǒng)計信息異步更新功能。 當(dāng)此選項設(shè)置為 ON 時,查詢不等待統(tǒng)計信息更新,即可進(jìn)行編譯。而過期的統(tǒng)計信息置于隊列中, 由后臺進(jìn)程中的工作線程來更新。查詢和任何其他并發(fā)查詢都通過使用現(xiàn)有的過期統(tǒng)計信息立即編譯。 由于不存在等待更新后的統(tǒng)計信息的延遲,因此查詢響應(yīng)時間可預(yù)測;但是過期的統(tǒng)計信息可能導(dǎo)致查詢優(yōu)化器選擇低效的查詢計劃。 在更新后的統(tǒng)計信息就緒后啟動的查詢將使用那些統(tǒng)計信息。這可能會導(dǎo)致重新編譯緩存的計劃(取決于較舊的統(tǒng)計信息版本)。 如果在同一個顯式用戶事務(wù)中出現(xiàn)某些數(shù)據(jù)定義語言 (DDL) 語句(例如,CREATE、ALTER 和 DROP 語句),則無法更新異步統(tǒng)計信息。

AUTO_UPDATE_STATISTICS_ASYNC 選項設(shè)置于數(shù)據(jù)庫級別,并確定用于數(shù)據(jù)庫中所有統(tǒng)計信息的更新方法。 它只適用于統(tǒng)計信息更新,而無法用于以異步方式創(chuàng)建統(tǒng)計信息。只有將 AUTO_UPDATE_STATISTICS 設(shè)置為 ON 時, 將此選項設(shè)置為 ON 才有效。默認(rèn)情況下,AUTO_UPDATE_STATISTICS_ASYNC 選項設(shè)置為 OFF。

從以上說明中,我們可以看出,對于大表,還是有可能存在統(tǒng)計信息更新不及時的時候,這時,就可能會影響查詢優(yōu)化器的判斷了。
有些人可能有個經(jīng)驗:對于一些慢的查詢,他們會想到重建索引來嘗試解決。其實(shí)這樣做是有道理的。 因為,在某些時候一個查詢突然變慢了,可能和統(tǒng)計信息更新不及時有關(guān),進(jìn)而會影響查詢優(yōu)化器的判斷。 如果此時重建索引,就可以讓查詢優(yōu)化器知道最新的數(shù)據(jù)分布,自然就可以避開這個問題。 還記得我前面用【set statistics profile on】顯示的執(zhí)行過程表格嗎?注意哦,那個表格就顯示每個步驟的實(shí)際數(shù)據(jù)量和預(yù)估的數(shù)據(jù)量。要不要重建索引,其實(shí)我們可以用【set statistics profile on】來看一下,如果實(shí)際數(shù)據(jù)量和預(yù)估的數(shù)據(jù)量的差值比較大, 那么我們可以考慮手工去更新統(tǒng)計信息,然后再去試試。

回到頂部優(yōu)化視圖查詢

再來說說優(yōu)化視圖查詢,雖然視圖也是由一個查詢語句定義的,本質(zhì)上也是一個查詢,但它和一般的查詢語句在優(yōu)化時,還是有所區(qū)別的。 這里主要的區(qū)別在于,視圖雖然是由一個查詢語句定義的,但如果只去分析這個查詢定義,可能得到的意義不大,因為視圖多數(shù)時候就不是直接使用, 而是在使用前,會加上where語句,或者放在其它語句中供from子句所使用。下面還是舉個例子吧,在我的演示數(shù)據(jù)庫中有個視圖OrdersView,定義代碼前面有。 我們來看看,如果直接使用這個視圖,會有什么樣的執(zhí)行計劃出來:

從這個視圖可以看出,SQL Server會對表Orders做全表掃描,應(yīng)該是很低效的。再來看看下面這個查詢:

從這個執(zhí)行計劃可以看出,與上面那個就不一樣了。前一個查詢中對Orders表的查找是使用【Clustered Index Scan】的方式, 而現(xiàn)在在使用【Clustered Index Seek】的方式了,最右邊二個步驟的成本的百分比也發(fā)生了改變。這樣就足以說明,優(yōu)化視圖時, 最好能根據(jù)實(shí)際需求,應(yīng)用不同的過濾條件,再來決定如何去優(yōu)化。

再來一個由三個查詢組成的情況來看看這個視圖的執(zhí)行計劃。

select * from dbo.OrdersView where OrderId = 1;
select * from dbo.OrdersView where CustomerId = 1;
select * from dbo.OrdersView where OrderDate >= '2010-12-1' and OrderDate  '2011-12-1';

很明顯,對于同一個視圖,在不同的過濾條件下,執(zhí)行計劃的差別很明顯。

推薦閱讀-MSDN文章

索引統(tǒng)計信息
http://msdn.microsoft.com/zh-cn/library/ms190397(SQL.90).aspx

查詢優(yōu)化建議
http://msdn.microsoft.com/zh-cn/library/ms188722(SQL.90).aspx

用于對運(yùn)行慢的查詢進(jìn)行分析的清單
http://msdn.microsoft.com/zh-cn/library/ms177500(SQL.90).aspx

邏輯運(yùn)算符和物理運(yùn)算符引用
http://msdn.microsoft.com/zh-cn/library/ms191158(SQL.90).aspx

您可能感興趣的文章:
  • sqlserver關(guān)于分頁存儲過程的優(yōu)化【讓數(shù)據(jù)庫按我們的意思執(zhí)行查詢計劃】
  • 教你如何看懂SQL Server查詢計劃

標(biāo)簽:南昌 珠海 晉中 東營 咸寧 石家莊 煙臺 北海

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《深入分析SqlServer查詢計劃》,本文關(guān)鍵詞  深入分析,SqlServer,查詢,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《深入分析SqlServer查詢計劃》相關(guān)的同類信息!
  • 本頁收集關(guān)于深入分析SqlServer查詢計劃的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    99欧美精品| 色综合综合网| 福利电影在线| 99久久国产综合精品色伊| 日本三级免费观看| 波多野结衣家庭教师在线| 一本色道久久88| 国产精品国码视频| 一级特黄大欧美久久久| 性色av一区二区三区在线观看| 在线观看不卡av| 中文在线a√在线8| 国产喷白浆一区二区三区| 一区二区视频在线观看免费的| 欧美激情亚洲色图| 亚洲欧美日韩国产另类专区| 日韩欧美久久久| 国产激情视频一区二区三区| 久久精品一二三四| 在线免费观看av的网站| 国产精品久久麻豆| 国产免费拔擦拔擦8x高清在线人| 成人欧美视频在线| 精品欧美久久久| 91精品国产66| 国产伦一区二区三区色一情| 免费在线观看日韩视频| 天天操天天操天天操天天| 范冰冰一级做a爰片久久毛片| 波多野结衣作品集| 中文字幕视频在线免费| 91丨porny丨国产| 成人黄色a**站在线观看| 精品国产一区二区三区免费| 欧美手机在线视频| 国产精品美女久久久久高潮| 香蕉av在线播放| 成人精品天堂一区二区三区| 亚洲欧洲一区二区在线观看| 视频一区三区| 在线播放亚洲激情| 免费在线欧美视频| 日本福利片在线观看| 国产欧美日韩91| www.av视频| 麻豆一区区三区四区产品精品蜜桃| 九色精品视频在线观看| 日韩不卡在线观看| 欧美午夜精品久久久久久孕妇| 欧美精品一区二区三区在线看午夜| 国产一级不卡视频| 久久久电影一区二区三区| 青春草国产成人精品久久| 日本私人影院在线观看| 日本精品一区二区三区在线播放| 国内三级在线观看| 亚洲精品自拍网| 国产精品久久久久7777| 国产精品久久久久久久久久久久久久久久久久| 久久艹在线视频| 欧美日韩中文字幕综合视频| 亚洲精品韩国| 91精东传媒理伦片在线观看| 国产精品素人视频| 蜜桃传媒麻豆第一区在线观看| 亚洲激情自拍偷拍| 国产成人毛片| 成年大片免费视频播放二级| 销魂美女一区二区| 亚洲一区二区在线看| 色中色综合影院手机版在线观看| 国产午夜精品视频一区二区三区| 777777av| 亚洲一级片免费观看| 欧美一区二区三级| 年下总裁被打光屁股sp| 中文字幕在线视频免费观看| 69视频免费看| 俺来俺也去www色在线观看| 日韩精品福利在线| 92久久精品一区二区| 亚洲电影有码| 亚洲国产美女精品久久久久∴| 中国一级特黄录像播放| 日本三级中文字幕在线观看| 中文字幕亚洲日本岛国片| 欧美区一区二| 色悠悠久久综合网| 情趣网站在线观看| 国产视频在线一区二区| 日韩女优中文字幕| av在线播放免费| 中文字幕22页| 中文字幕在线中文字幕在线中三区| 成人av在线资源网站| 欧美一区=区三区| 成人看片黄a免费看在线| 国产一区二区在线免费| 日韩激情文学| 亚洲色图图片网| 色综合久久五月| 国产成人av一区二区三区| 北条麻妃一区二区三区在线| 日韩精品专区在线影院观看| 欧美一级视频在线播放| 亚洲国产欧美国产综合一区| 亚洲精品美女在线观看播放| chinese偷拍一区二区三区| 黄色在线观看视频网站| 蜜臀91精品一区二区三区| 日本视频免费一区| 成年人视频网站免费| 国产成人无码www免费视频播放| 日韩精品三级| 亚洲精品国久久99热| 中文字幕一区二区精品| 50路60路老熟妇啪啪| 欧美人与禽性xxxxx杂性| 亚洲欧洲综合| 红桃视频一区二区三区免费| 久久综合视频网| 午夜伦伦电影理论片费看| 欧美日韩一级二级三级| 天堂在线视频中文网| 俺来俺也去www色在线观看| 久久国产福利| 丝袜脚交免费网站xx| 久久先锋影音av鲁色资源| 中文国语毛片高清视频| 精品少妇一区二区三区在线| 六月丁香在线视频| 欧美一区二区三区网站| jizz在亚洲| 国产精品一区二区三区观看| av中文字幕在线观看| 香蕉一区二区| 一区二区三区免费在线| 国产精品揄拍500视频| 国产成年人免费视频| 欧美在线视频导航| 小明看看成人免费视频| 一区二区三区无码高清视频| 亚洲视频一二三四| 欧美三片在线视频观看| 99久久99久久久精品齐齐| 国产精品美女在线观看直播| 成人在线视频网址| 色综合色综合久久综合频道88| 午夜宅男久久久| 午夜男人天堂| 91在线视频精品| 国产奶头好大揉着好爽视频| 91麻豆国产自产在线观看| 久久亚洲国产中v天仙www| 一区二区冒白浆视频| 国产午夜久久| 999精品在线视频| 7777奇米亚洲综合久久| 亚洲成人动漫在线观看| 国产精品青草综合久久久久99| 激情综合色丁香一区二区| 26uuu亚洲伊人春色| 免费试看一区| 欧美日韩国产中文| 国产精品免费观看久久| 午夜精品久久久久久久蜜桃app| 亚洲国产成人久久| 国产农村老头老太视频| 国产精区一区二区| 欧美老女人性生活视频| 国产精品最新乱视频二区| 国产精品久久久久久久久果冻传媒| 国产一区视频网站| 亚洲无码精品在线观看| 国产精品免费看久久久香蕉| 激情综合在线观看| 亚洲激情一区| 欧美在线日韩在线| 免费wwwxxx| frxxee中国xxx麻豆hd| 久久国产小视频| 色爱综合av| 中文字幕一区二区三区在线观看| 国产精品久久午夜夜伦鲁鲁| 福利视频一区二区| 亚洲同志男男gay1069网站| av中文天堂在线| 狠狠色狠狠色综合人人| 视频一区二区三区中文字幕| 欧美国产偷国产精品三区| av在线这里只有精品| 国产精品一区二区av| 国产丰满美女做爰| 久久人妻无码aⅴ毛片a片app| 精品国产丝袜高跟鞋| 中文字幕中文字幕中文字幕亚洲无线| 欧洲一区av| h文在线观看免费| 男人天堂网页| 日韩精品久久久久久| 蜜桃免费一区二区三区| 爽爽影院免费观看视频| 极品在线视频| 日韩欧美在线第一页| 国产精品亚洲а∨天堂免在线| 国产亚洲一区在线| 男人猛进猛出女人屁股视频| 很黄很色网站| 97一区二区三区| 久久国产露脸精品国产| 国产精品久久久久久亚洲毛片| 美女扒开尿口让男人操亚洲视频网站| 亚洲第一页综合| 国精产品一区二区| 在线日韩日本国产亚洲| 欧美日韩精品一区二区三区在线观看| 自拍偷拍欧美精品| 影音先锋电影在线观看| 久热在线观看视频| 欧美亚洲综合一区| 亚洲国产精品123| 国产精品久久久久久影视| 二区三区四区高清视频在线观看| 国产日韩精品一区| 97人妻精品一区二区三区免费| 国产精品日韩一区二区三区| 麻豆传媒在线视频| 国产精品mv在线观看| 欧美中文娱乐网| 日韩中文字幕三区| 4438全国成人免费| 国产乱码久久久| 中文字幕91| 国产精品videossex| 国产精品 欧美 日韩| 91免费人成网站在线观看18| 亚洲午夜国产成人av电影男同| 99riav国产精品视频| 午夜欧美视频在线观看| 明星乱亚洲合成图.com| 国产精品涩涩涩视频网站| 午夜免费视频在线国产| 最近2019年中文视频免费在线观看| 日日躁夜夜躁白天躁晚上躁91| 在线视频福利一区| 国产成人禁片免费观看视频| 韩国黄色一级大片| 国模精品视频一区二区三区| 少妇按摩一区二区三区| 成人乱码一区二区三区| 欧美中文在线观看| 女人18毛片毛片毛片毛片区二| www.国产色| 国产精选一区二区三区不卡催乳| 国产日产欧美一区| 国产综合av一区二区三区| 国精品无码一区二区三区| 在线观看亚洲专区| 在线视频综合导航| √天堂资源在线| 色婷婷一区二区三区四区| av先锋资源| 色呦呦一区二区三区| 久久精品人人爽人人爽| 污网站在线播放| 成人天堂入口网站| 青娱乐av在线| 欧美激情精品久久久久久| 老司机福利在线视频| 国产美女视频免费观看下载软件| 男女啪啪网站| 欧美在线免费看视频| 国产主播在线观看| 欧美另类极品videosbestfree| 在线观看欧美黄色| 成人性生交大片免费看午夜| 最新福利小视频在线播放| 欧美色图亚洲天堂| 韩国三级中文字幕hd久久精品| 婷婷亚洲五月色综合| 日本久久精品视频| 亚洲一区二区乱码| 毛片激情在线观看| 看**视频a级毛片| 欧美一站二站| 国产91社区| 亚洲啊v在线| 国产av熟女一区二区三区| 久久琪琪电影院| 久久久999久久久| 91中文精品字幕在线视频| 性一交一乱一透一a级| 国产成人免费高清| 热这里只有精品| 蜜桃一区二区三区四区| 一区二区欧美国产| 欧美日韩亚洲综合一区二区三区| 国产精品成人免费精品自在线观看| 欧美自拍一区| 国产男男chinese网站| 777久久久精品一区二区三区| 国产精品美女| 国产主播喷水一区二区| 日韩不卡一二区| 亚洲国产中文字幕久久网| 精品视频—区二区三区免费| 国产精品视频午夜| 久久免费电影网| 精品日本12videosex| 四虎国产精品永久地址998| 日本一区二区三区dvd视频在线| 国产日韩欧美一区二区三区在线观看| 久久精品无码一区二区三区| 午夜小视频在线| 日本三级久久久| 欧美激情第3页| 2024最新电影在线免费观看| 136福利第一导航国产在线| 国产美女视频一区二区三区| 日本理论中文字幕| 五月天久久综合网| 不卡视频在线播放| 麻豆免费看一区二区三区| 亚洲久久久久| 九9re精品视频在线观看re6| 在线影音av| 午夜精品偷拍| 又色又爽又黄视频|