如果在執行計劃中看到如下所示的任何一項,就應該將它們視作警告信號并調查它們以找出潛在的性能問題。從性能方面來說,下面所示的每一項都是不理想的。
Index or table scans(索引或者表掃描):可能意味著需要更好的或者額外的索引。
Bookmark Lookups(書簽查找):考慮修改當前的聚集索引,使用復蓋索引,限制SELECT語句中的字段數量。
Filter(過濾):在WHERE從句中移除用到的任何函數,不要在SQL語句中包含視圖,可能需要額外的索引。
Sort(排序):數據是否真的需要排序?可否使用索引來避免排序?在客戶端排序是否會更加有效率?
查看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條件句中用到的字段選擇性不高。在任何情況下,與標準的表掃描不同,聚集索引掃描并不會總是去查找數據表中的所有數據,所以聚集索引掃描一般都會比標準的表掃描要快。通常來說,要將聚集索引掃描改成聚集索引查找,你唯一能做的是重寫查詢語句,讓語句限制性更多,從而返回更少的數據行。
絕大多數情況下,查詢優化器會對連接進行分析,按最有效率的順序,使用最有效率的連接類型來對數據表進行連接。但并不總是如此。在圖形執行計劃中你可以看到代表查詢所使用到的各種不同連接類型的圖標。此外,每個連接圖標都有兩個箭頭指向它。指向連接圖標的上面的箭頭代表該連接的外部表,下面的箭頭則代表這個連接的內部表。箭頭的另一頭則指向被連接的數據表名。
有時在多表連接的查詢中,箭頭的另一頭指向的并不是一個數據表,而是另一個連接。如果將鼠標移到指向外部連接與內部連接的箭頭上,就可以看到一個彈出式窗口,告訴你有多少數據行被發送至這個連接來進行處理。外部表應該總是比內部表含有更少的數據行。如果不是,則說明查詢優化器所選擇的連接順序可能不正確(下面是關于這個話題的更多信息)。
首先,讓我們來看看連接類型。SQL Server可以使用三種不同的技術來連接資料表:嵌套循環(nested loop),散列(hash),以及合并(merge)。一般來說,嵌套循環是最快的連接類型,但如果不可能使用嵌套循環的話,則會用到散列或者合并作為合適的連接類型。兩者都比嵌套循環連接慢。
當連接大表時,則合并連接可能是最佳選項,而非嵌套循環連接。唯一的明確這一點的方式是對兩者都進行測試以查看哪一個最有效率。
如果你懷疑某個查詢速度慢的原因可能是因為它所使用的連接類型不理想,那么你可以使用連接提示來復蓋查詢優化器的選擇。在使用連接提示之前,你需要花費一些時間去了解一下每種連接類型以及它們的工作方式。這是一個復雜的話題,超出了本文的討論范圍。
查詢優化器選擇最有效率的連接類型來連接數據表。例如,嵌套循環連接的外部表應該是連接的兩個表中較小的那個表。散列連接也是一樣,它的外部表應該是較小的那個表。如果你覺得查詢優化器選擇的連接順序是錯誤的,可以使用連接提示來復蓋它。
你常常會在圖形執行計劃上看到標識成”書簽查找(Bookmark Lookup)”的圖標。書簽查找相當常見。書簽查找的本質是告訴你查詢處理器必須從數據表或者聚集索引中來查找它所需要的數據行,而不是從非聚集索引中直接讀取。
打比方說,如果一個查詢語句的SELECT,JOIN以及WHERE子句中的所有字段,都不存在于那個用來定位符合查詢條件的數據行的非聚集索引中,那么查詢優化器就不得不做額外的工作在數據表或聚集索引中查找那些滿足這個查詢語句的字段。
另一種引起書簽查找的原因是使用了SELECT *。由于在絕大多情況下它會返回比你實際所需更多的數據,所以應該永不使用SELECT *.
從性能方面來說,書簽查找是不理想的。因為它會請求額外的I/O開銷在字段中查找以返回所需的數據行。
如果認為書簽查找防礙了查詢的性能,那么有四種選擇可以用來避免它:可以建立WHERE子句會用到的聚集索引,利用索引交集的優勢,建立覆蓋的非聚集索引,或者(如果是SQL Server 2000/2005企業版的話)可以建立索引視圖。如果這些都不可能,或者使用它們中的任何一個都會耗用比書簽查找更多的資源,那么書簽查找就是最佳的選擇了。[
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/xiao_hn/archive/2009/06/11/4259628.aspx
posted on 2010-04-15 17:12
何克勤 閱讀(205)
評論(0) 編輯 收藏 所屬分類:
數據庫和SQL