如何查看SQL server 執行計劃

歡迎轉載。轉載請保留原作者姓名以及原文地址,並請註明譯文出處:http://blog.csdn.net/xiao_hn

 

 

當需要分析某個查詢的效能時,最好的方式之一查看這個查詢的執行計劃。執行計劃描述SQL Server查詢優化器如何實際運行(或者將會如何運行)一個特定的查詢。

 

查看查詢的執行計劃有幾種不同的方式。它們包括:

 

SQL Server查詢分析器裏有一個叫做顯示實際執行計劃的選項(位於查詢下拉菜單中)。如果打開了這個選項,那麼無論何時在查詢分析器中運行一個查詢,都會得到一個顯示在單獨窗口的查詢執行計劃(以圖形的格式)

 

如果只是想看下執行計劃而不想運行查詢,那麼可以選擇顯示預估的執行計劃選項(位於查詢下拉菜單中)。當選擇這個選項後,執行計劃會馬上顯示出來(以圖形的格式)。兩者的不同之處在於當實際運行一個查詢時,當前的服務器上的運算也會被考慮進去。大多數情況下,兩種方式產生的執行計劃產生的結果是相似的。

 

當建立一個SQL Server Profiler追蹤時,可以收集的一個事件是MISC: Execution Plan.這個信息(以文本的形式)顯示查詢優化器用來執行查詢的計行計劃。

 

可以在查詢分析器上執行SET SHOWPLAN_TEXT ON命令。這條命令被執行後,所有在當前這個查詢分析器會話中執行的查詢都不會運行,而是會顯示一個基於文本的執行計劃。執行某條用到臨時表的查詢時,必須在執行查詢先運行SET STATISTICS PROFILE ON語句。

 

上面這些選項中,我更喜歡使用顯示實際執行計劃這個選項。它以圖形的方式輸出信息,並且考慮到了當前服務器上的那些運算。[7.0, 2000] Updated 8-5-2005

 

*****

 

如果在執行計劃中看到如下所示的任何一項,就應該將它們視作警告信號並調查它們以找出潛在的性能問題。從性能方面來說,下面所示的每一項都是不理想的。

 

Index or table scans(索引或者表掃描)可能意味着需要更好的或者額外的索引。

Bookmark Lookups(書籤查找)考慮修改當前的聚集索引,使用覆蓋索引,限制SELECT語句中的字段數量。

Filter(過濾)WHERE從句中移除用到的任何函數,不要在SQL語句中包含視圖,可能需要額外的索引。

Sort(排序)數據是否真的需要排序?可否使用索引來避免排序?在客戶端排序是否會更加有效率?

 

無一例外地避免這些操作是不可能的,但是避免得越多,查詢性能就會越快。[7.0,2000,2005]

 

*****

 

如果有在存儲過程中或者其它T-SQL批處理代碼中用到了臨時表,就不能在查詢分析器或Management Studio使用顯示預估的執行計劃選項來評估查詢。必須實際運行這個存儲過程或者批處理代碼。這是因爲使用顯示預估的執行計劃選項來運行一個查詢時,它並沒有實際被運行,臨時表也沒有創建。由於臨時表沒有被創建,參考到臨時表的代碼就會失敗,導致預估的執行計劃不能成創建成功。

 

從另一方面來說,如果使用的是表變量而不是臨時表,則可以使用顯示預估的執行計劃選項。[7.0,2000,2005] Updated 8-5-2005

 

*****

 

 

如果在查詢分析器或Management Studio中對一個非常複雜的查詢的執行計劃進行分析,可能會覺得它的執行計劃既難於看懂也難於分析。那麼,按照查詢的邏輯將它拆分成幾個部分,然後分別對這些部分進行分析會容易得多。[7.0,2000,2005] Updated 8-5-2005

 

*****

 

 

圖形執行計劃並不總是容易讀懂和解釋。查看執行計劃時記住如下幾點:

 

非常複雜的執行計劃會被分成多個部分,它們分別列出在屏幕上。每個部分分別代表查詢優化器爲了得到最終結果而必須執行的單個處理或步驟。

 

執行計劃的每個步驟經常會被拆分成一個個更小的子步驟。不幸的是,它們是從右至左顯示在屏幕上的。這意味着你必須滾動到圖形執行計劃的最右邊去查看每個步驟是從哪兒開始的。

 

每個步驟與子步驟間通過箭頭連接,藉此顯示查詢執行的路徑。

 

最後,查詢的所有部分在屏幕頂部的左邊彙總到一起。

 

如果將鼠標移動到任何執行計劃任何步驟或者子步驟的上面,就會顯示一個彈出式窗口,上面顯示該步驟或子步驟的更加詳細的信息。

 

如果將鼠標移動到連接步驟或子步驟的箭頭上,就可以看到一個彈出式窗口,上面顯示有多少筆記錄從一個步驟或子步驟移動到另一個步驟或子步驟。

[7.0, 2000, 2005] Updated 8-5-2005

 

 

圖形執行計劃上連接每個圖標的箭頭粗細不同。箭頭的粗細表示每個圖標之間移動的數據行數量以及數據行大小移動所需的相對成本。箭頭越粗,相對成本就越高。

 

 

可以使用這個指示器來快速測量一個查詢。你可能會特別關注粗箭頭以瞭解它如何影響到查詢的效能。例如,粗線頭應該在圖形執行計劃的右邊,而非左邊。如果看到它們在左邊,就意味着太多的數據行被返回,這個執行計劃也不是最佳的執行計劃。[7.0,2000,2005]

*****

 

 

執行計劃的每個部分都被分配了一個成本百分比。它表示這個部分耗用了整個執行計劃的多少資源。當對一個執行計劃進行分析的時候,應該將精力集中於有着高成本百分比的那些部分。這樣就可以在有限的時間裏找到可能性最大的問題,從而回報了你在時間上的投資。[7.0, 2000, 2005]

*****

 

 你可能會注意到一個執行計劃的某些部分被執行了不止一次。作爲執行計劃分析的一部分,應該將你的一些時間集中在任何執行了超過一次的那些部分上,看看是否有什麼方式減少它們執行的次數。執行的次數越少,查詢的速度就越快。[7.0, 2000, 2005]

*****

 

 在執行計劃中你可以看到I/OCPU成本。它們沒有實際的意義,例如代表特定資源的使用量。查詢優化器使用這些數字來做出最佳選擇。它們可用來參考的一個意義是,較小的I/OCPU成本比較大的I/OCPU成本使用更少的服務器資源。[7.0, 2000, 2005]

*****

 

 

查看SQL Server圖形執行計劃時,可以查找的非常有用的一個東西就是查詢優化器如何爲給定的查詢使用索引來從表中獲取數據。通過查看是否有用到索引,以及索引如何被使用,都有助於判斷當前的索引是否使得查詢執行得儘可能的快。

將鼠標移到圖形執行計劃上的表名(以及它的圖標)上面,就會彈出一個窗口,從它上面可以看到一些信息。這些信息讓你知道是否有用到索引來從表中獲取數據,以及它是如何使用的。這些信息包括:

·     Table Scan(表掃描):如果看到這個信息,就說明數據表上沒有聚集索引,或者查詢優化器沒有使用索引來查找。意即資料表的每一行都被檢查到。如果資料表相對較小的話,表掃描可以非常快速,有時甚至快過使用索引。

因此,當看到有執行表掃描時,第一件要做的事就是看看數據表有多少數據行。如果不是太多的話,那麼表掃描可能提供了最好的總體效能。但如果數據表大的話,表掃描就極可能需要長時間來完成,查詢效能就大受影響。在這種情況下,就需要仔細研究,爲數據表增加一個適當的索引用於這個查詢。

假設你發現某查詢使用了表掃描,有一個合適的非聚集索引,但它沒有用到。這意味着什麼呢?爲什麼這個索引沒有用到呢?如果需要獲得的數據量相對數據表大小來說非常大,或者數據選擇性不高(意味着同一個字段中重複的值很多),表掃描經常會比索引掃描快。例如,如果一個數據表有10000個數據行,查詢返回1000行,如果這個表沒有聚集索引的話,那麼表掃描將比使用一個非聚集索引更快。或者如果數據表有10000個數據行,且同一個字段(WHERE條件句有用到這個字段)上有1000筆重複的數據,表掃描也會比使用非聚集索引更快。

查看圖形執行計劃上的數據表上的彈出式窗口時,請注意預估的資料行數(Estimated Row Count)”。這個數字是查詢優化器作出的多少個數據行會被返回的最佳推測。如果執行了表掃描且預估的數據行數數值很高的話,就意味着返回的記錄數很多,查詢優化器認爲執行表掃描比使用可用的非聚集索引更快。

·     Index Seek(索引查找):索引查找意味着查詢優化器使用了數據表上的非聚集索引來查找數據。性能通常會很快,尤其是當只有少數的數據行被返回時。

·     Clustered Index Seek(聚集索引查找):這指查詢優化器使用了數據表上的聚集索引來查找數據,性能很快。實際上,這是SQL Server能做的最快的索引查找類型。

·     Clustered Index Scan(聚集索引掃描):聚集索引掃描與表掃描相似,不同的是聚集索引掃描是在一個建有聚集索引的數據表上執行的。和一般的表掃描一樣,聚集索引掃描可能表明存在效能問題。一般來說,有兩種原因會引此聚集索引掃描的執行。第一個原因,相對於數據表上的整體數據行數目,可能需要獲取太多的數據行。查看預估的數據行數量(Estimated Row Count)”可以對此加以驗證。第二個原因,可能是由於WHERE條件句中用到的字段選擇性不高。在任何情況下,與標準的表掃描不同,聚集索引掃描並不會總是去查找數據表中的所有數據,所以聚集索引掃描一般都會比標準的表掃描要快。通常來說,要將聚集索引掃描改成聚集索引查找,你唯一能做的是重寫查詢語句,讓語句限制性更多,從而返回更少的數據行。

[7.0, 2000, 2005]

 

絕大多數情況下,查詢優化器會對連接進行分析,按最有效率的順序,使用最有效率的連接類型來對數據表進行連接。但並不總是如此。在圖形執行計劃中你可以看到代表查詢所使用到的各種不同連接類型的圖標。此外,每個連接圖標都有兩個箭頭指向它。指向連接圖標的上面的箭頭代表該連接的外部表,下面的箭頭則代表這個連接的內部表。箭頭的另一頭則指向被連接的數據表名。

 

 

有時在多表連接的查詢中,箭頭的另一頭指向的並不是一個數據表,而是另一個連接。如果將鼠標移到指向外部連接與內部連接的箭頭上,就可以看到一個彈出式窗口,告訴你有多少數據行被髮送至這個連接來進行處理。外部表應該總是比內部表含有更少的數據行。如果不是,則說明查詢優化器所選擇的連接順序可能不正確(下面是關於這個話題的更多信息)

 

 

首先,讓我們來看看連接類型。SQL Server可以使用三種不同的技術來連接資料表:嵌套循環(nested loop),散列(hash),以及合併(merge)。一般來說,嵌套循環是最快的連接類型,但如果不可能使用嵌套循環的話,則會用到散列或者合併作爲合適的連接類型。兩者都比嵌套循環連接慢。

 

 

當連接大表時,則合併連接可能是最佳選項,而非嵌套循環連接。唯一的明確這一點的方式是對兩者都進行測試以查看哪一個最有效率。

 

 

如果你懷疑某個查詢速度慢的原因可能是因爲它所使用的連接類型不理想,那麼你可以使用連接提示來複蓋查詢優化器的選擇。在使用連接提示之前,你需要花費一些時間去了解一下每種連接類型以及它們的工作方式。這是一個複雜的話題,超出了本文的討論範圍。

 

 

查詢優化器選擇最有效率的連接類型來連接數據表。例如,嵌套循環連接的外部表應該是連接的兩個表中較小的那個表。散列連接也是一樣,它的外部表應該是較小的那個表。如果你覺得查詢優化器選擇的連接順序是錯誤的,可以使用連接提示來複蓋它。

 

 

很多情況下,唯一的確認使用連接提示改變連接類型或連接順序是提升還是降低了效能的方式,就是對它們進行測試,看看發生了什麼。[7.0, 2000, 2005]

*****

 

如果你的SQL Server有多個CPU,並且沒有修改SQL Server的默認設置來限制SQL Server使用服務器上所有CPU的能力,那麼查詢優化器會考慮使用平行處理(parallelism)來執行某些查詢。平行處理指在多個CPU上同時運行一個查詢的能力。很多情況下,一個運行在多個處理器上的查詢比僅運行在單個處理器上的查詢要快,但並不總是這樣。

 

 

查詢優化器並不會總是使用平行處理,即使在它能使用的時候。這是因爲查詢優化器在決定使用平行處理前會考慮到各種不同的因素。例如當前SQL Server上處於活動狀態的連接數量,CPU忙碌程度,是否有足夠的內存來運行平行化查詢,需要處理的數據行數量,以及這個查詢的類型。查詢優化器收集到這些真實的數據後,再決定平行處理是不是運行這個查詢的最佳選擇。你可能會發現,某次一個查詢沒有用到平行處理,但稍後某次再次運行同樣的查詢時,卻又用到了平行處理。

 

 

有時,使用多個處理器所需的花費會大於使用它們能所能節省的資源。儘管查詢處理器的確會衡量使用平行查詢的正反兩面的影響,但它的猜想並不總是正確的。

 

 

如果懷疑平行處理防礙了某條查詢的性能,你可以使用OPTION (MAXDOP 1)提示來關閉該查詢的平行處理。

決定是否使用平行處理的唯一方式是通過這兩種方式對查詢進行測試,看看發生了什麼。[7.0, 2000, 2005]

*****

 

 

查看圖形執行計劃時,你可能會發現某個圖標的文字用紅色顯示,而非通常情況下的黑色。這意味着相關的表的一些統計數據遺失,統計數據是查詢優化器生成一個好的執行計劃所必須的。

 

 

遺失的統計數據可以通過右鍵這個圖標,並選擇創建遺失的統計資料來創建。這時會彈出創建遺失的統計數據對話框,通過它可以很容易地創建遺失的統計數據。

 

 

當可以選擇去更新遺失的統計資料時,應該總是這樣做,因爲這樣極有可能讓你正在分析的查詢語句從中獲得效能上的好處。[7.0, 2000, 2005]

*****

 

 

有時你會在圖形執行計劃上看到標識了”Assert”的圖標。這意味着查詢優化器正在驗證查詢語句是否有違反引用完整性或者條件約束。如果沒有,則沒有問題。但如果有的話,查詢優化器將無法爲該查詢建立執行計劃,同時會產生一個錯誤。[7.0, 2000, 2005]

*****

 

 

你常常會在圖形執行計劃上看到標識成書籤查找(Bookmark Lookup)”的圖標。書籤查找相當常見。書籤查找的本質是告訴你查詢處理器必須從數據表或者聚集索引中來查找它所需要的數據行,而不是從非聚集索引中直接讀取。

 

 

打比方說,如果一個查詢語句的SELECT,JOIN以及WHERE子句中的所有字段,都不存在於那個用來定位符合查詢條件的數據行的非聚集索引中,那麼查詢優化器就不得不做額外的工作在數據表或聚集索引中查找那些滿足這個查詢語句的字段。

 

 

另一種引起書籤查找的原因是使用了SELECT *。由於在絕大多情況下它會返回比你實際所需更多的數據,所以應該永不使用SELECT *.

 

 

從性能方面來說,書籤查找是不理想的。因爲它會請求額外的I/O開銷在字段中查找以返回所需的數據行。

 

 

如果認爲書籤查找防礙了查詢的性能,那麼有四種選擇可以用來避免它:可以建立WHERE子句會用到的聚集索引,利用索引交集的優勢,建立覆蓋的非聚集索引,或者(如果是SQL Server 2000/2005企業版的話)可以建立索引視圖。如果這些都不可能,或者使用它們中的任何一個都會耗用比書籤查找更多的資源,那麼書籤查找就是最佳的選擇了。[7.0, 2000, 2005]

 

有時查詢優化器需要在tempdb數據庫中建立臨時工作表。如果是這樣的話,就意味着圖形執行計劃中有標識成Index Spool, Row Count Spool或者Table Spool的圖標。

 

 

任何時候,使用到工作表一般都會防礙到性能,因爲需要額外的I/O開銷來維護這個工作表。理想情況下應該不要用到工作表。不幸的是並不能總是避免用到工作表。有時當使用工作表比其它選擇更有效率時,它的使用實際上會增強性能。

 

 

不論何種情況,圖形執行計劃中的工作表都應該引起你的警覺。應該仔細檢查這樣的查詢語句,看看是否有辦法重寫查詢來避免用到工作表。有可能沒有辦法。但如果有的話,你就朝提升這個查詢的性能方面前進了一步。[7.0, 2000, 2005]

*****

 

 

在圖形執行計劃上看到流聚合(Stream Aggregate)圖標就意味着有對一個單一的輸入進行了聚合。當使用了DISTINCT子句,或者任何聚合函數時,如AVG, COUNT, MAX, MIN,或者SUM等,流聚合操作就相當常見。  [7.0, 2000, 2005]

*****

 

 

查詢分析器與Management Studio不是唯一的可以生成顯示查詢執行計劃的工具。SQL Server Profiler也可以顯示執行計劃,但格式是文本形式的。使用SQL Server Profiler來顯示執行計劃的一個優勢是,它能爲實際運行的大量查詢產生執行計劃。如果使用查詢分析器和Management Studio,則一次只能運行一個。

 

 

使用Profiler捕獲、顯示執行計劃時,必須使用如下的配置生成一個追蹤:

 

捕獲事件

·     Performance: Execution Plan

·     Performance: Show Plan All

·     Performance: Show Plan Statistics

·     Performance: Show Plan Text

 

顯示的字段

·     StartTime

·     Duration

·     TextData

·     CPU

·     Reads

·     Writes

 

過濾條件

·     Duration。你會想指定最大的查詢執行時間,例如5秒鐘,由此避免得到太大量的數據。

 

當然,你可以在你的追蹤中捕獲更多的沒有例在上面的信息,上面例出的只是一個指南而已。但必須記住不要去捕獲太多的數據,否則,追蹤的運行會影響服務器的性能。[7.0, 2000, 2005]

*****

 

 

如果在查詢中使用了OPTION FAST提示,那就必須小心執行計劃的結果可能不是你所期望的。這時你所看到的執行計劃基於使用了FAST提示的結果,而不是整個查詢語句的實際執行計劃。

 

 

FAST提示用來告知果詢優化器儘可能快地返回指定行數的數據行,即便這樣做會防礙查詢的整體性能。使用這個提示的目的在於爲使用者快速返回特定行數的記錄,由此讓他們產生速度非常快速的錯覺。。當返回指定行數的數據行後,剩餘的數據行按照它們通常的速度返回。

 

 

因此,如果使用了FAST提示,那麼生成的執行計劃只是基於那些FAST返回的數據行,而非查詢要返回的所有數據行。如果想看所有數據行的執行計劃,那麼就必須移除這個FAST提示。[2000,2005]

發佈了12 篇原創文章 · 獲贊 3 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章