一直想找一些關於SQL語句性能調試的權威參考,可是有參考未必就可以作好調試 2的工做。我深信實踐中獲得的經驗是最珍貴的,書本知識只是一個引導。本篇來源於《Inside Microsoft SQL Server 2008》,有經驗的高手儘管拍磚把。html
這個部分將講解一些性能分析工具,這些性能分許主要關注在執行計劃。算法
緩存執行計劃 sql
SQL Server 2008提供了一些服務器對象來分析執行計劃
Sys.dm_exec_cached_plans: 包含緩存的執行計劃,每一個執行計劃對應一行。
Sys.dm_exec_plan_attributes: 這是一個系統函數,每個執行計劃都對應着一些屬性,在這個系統函數中包含着這些屬性。
Sys.dm_exec_sql_text: 這是一個系統函數,返回文字格式的執行計劃。
Sys.dm_exec_query_plan: 這是一個系統函數,返回xml格式的執行計劃。
SQL Server 2008還提供了一個兼容性的視圖sys.syscacheobject,這個視圖中保存了全部的執行計劃的信息。數據庫
清除緩存 緩存
在進行性能分析的時候有時候須要清除緩存以便進行下一次分析。SQL Server提供了一些工具來清除緩存的性能數據。使用下面的語句來完成這些任務。 服務器
清除全局緩存使用下面的語句: session
DBCC DROPCLEANBUFFERS;ide
從全局緩存中清除執行計劃,使用下面的語句: 函數
DBCC FREEPROCCACHE;工具
清除某一個數據庫中的執行計劃,使用下面的語句:
DBCC FLUSHPROCINDB(<db_id>);
清除一個特定的執行計劃使用下面的語句:
DBCC FREESYSTEMCACHE(<cachestore>);
可使用’ALL’,pool_name,’Object Plan’,’SQL Plans’,’Bound Trees’做爲輸入參數。’ALL’參數標明要清除全部的緩存,pool_name的值代表要清除的一個緩存池的名字。’Object Plans’清除對象計劃(例如存儲過程,觸發器,用戶定義函數等等)。’SQL Plans’用來清除要當即執行的語句。’Bound Trees’定義清除視圖,約束等的緩存。
注意:在使用這些語句清除緩存以前要想清楚,特別是在生產環境。這些對性能有很大的影響。清除這些緩存以後SQL Server須要從數據頁中從新讀取數據。而且SQL Server須要從新生成新的執行計劃。所以在清除以前要想清楚這些對生產或者測試環境的影響。
動態的管理對象
SQL Server 2005引入了動態管理對象,例如DMV,DMF。SQL Server 2008中添加了新的對象,新的屬性。這些飽含很是有用的信息,利用這些信息能夠監視SQL Server,診斷問題,進行性能監視。要仔細研究這些對象會很耗時。這裏只是列舉一些經常使用的。
統計IO
統計IO是是一個session選項。它返回域當前執行的語句相關的I/O信息。要使用這個選項首選清除數據緩存:
DBCC DROPCLEANBUFFERS;
而後運行下面的代碼來打開這個選項:
SET STATISTICS IO ON;
go //加上go才能運行
SELECT orderid, custid, empid, shipperid, orderdate, filler
FROM dbo.Orders
WHERE orderdate >= '20060101'
AND orderdate < '20060201';
go
最後能夠獲得相似下面的信息:
(21226 row(s) affected)
Table 'Orders'. Scan count 1, logical reads 537, physical reads 3, read-ahead reads 549, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
從輸出信息中咱們能夠看到在執行計劃中有多少次獲取表(Scan count);多少次讀取緩存(logical reads);多少次讀取硬盤(physical reads 俺的read-ahead reads);多少次讀取大的對象(lob physical reads , log read-ahead reads)。
使用下面的語句來關閉這個選項:
SET STATISTICS IO OFF;
統計運行時間
STATISTICS TIME是一個用來返回CPU時鐘時間的session選項。它返回語法分析,編譯,執行的時間。要使用這個選項首選要清除執行計劃緩存。
DBCC DROPCLEANBUFFERS;
DBCC FREEPROCCACHE;
運行下面的語句來打開相應的選項:
SET STATISTICS TIME ON;
運行下面的語句:
SELECT orderid, custid, empid, shipperid, orderdate, filler FROM dbo.Orders WHERE orderdate >= '20060101' AND orderdate < '20060201';
獲得下面的信息:
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 4 ms.
SQL Server Execution Times:
CPU time = 46 ms, elapsed time = 544 ms.
從這些信息中能夠得到執行這個語句時候的CPU時鐘時間,編譯時間,運行時間。運行下面的語句能夠關閉這個選項:
SET STATISTICS TIME OFF;
當須要分析一個單獨的語句的性能的時候這個選項很是有用。當須要使用批處理的模式來運行語句的時候須要度量會有所不一樣。在查詢以前保存SYSDATETIME函數的值,並寫入到一個表中。注意這個函數返回的時間格式是DATETIME2,能夠精確到100納秒。這個函數的準確性取決於計算機硬件和操做系統版本。由於這個函數會調用GetSystemTimeAsFileTime()這個WindowsAPI。須要統計時間的時候能夠重複地運行請求語句,而後記錄下須要的時間。
分析執行計劃
執行計劃是SQL優化器生成的如何處理給定的請求的一個工做計劃。它包含這個請求中藥用到的操做符。有一些操做可能會執行屢次。一些計劃分支可能會並行執行。在這個工做計劃中,優化器決定獲取語句中涉及到的表的順序,要使用到那些索引,要使用那些查詢方法,要使用那些算法等等。事實上,優化器會在多個執行計劃中選擇出一個最優的,資源耗費最少的。頻繁地生成執行計劃也會耗費時間,因此SQL Server也會根據數據量的大小估算生成執行計劃所須要的閥值時間。生成執行計劃的時間不會超過這個估算的閥值時間。還有一個閥值是根據耗費的資源計算獲得的。若是一個工做計劃的資源耗費低於這個閥值,就認爲它是足夠好的,優化器就會中止優化使用這個計劃。
圖形執行計劃
SSMS容許咱們查看一個圖形化的執行計劃(快捷鍵Ctrl+L)。注意當查看一個執行計劃的時候,查詢並無運行。一些度量值只能在運行完以後才能獲得(實際查詢獲得的行的數目)。
使用下面的語句來查看執行計劃:
SELECT custid, empid, shipperid, COUNT(*) AS numorders FROM dbo.Orders WHERE orderdate >= '20080201' AND orderdate < '20080301'
GROUP BY CUBE(custid, empid, shipperid);
這個語句查詢獲得全部可能的聚合值,聚合屬性是custid,empid,shipperid。如圖1
圖1
注意當這個執行計劃佔用很大的屏幕空間的時候能夠點擊右下方的按鈕「+」不放,而後拖動鼠標能夠查看想要查看的區域。
執行計劃是由一些操做組成的樹狀結構圖。數據從子運算流向父運算。這個結構的順序是從右到左,從上到下。在這個例子中,運算首選從彙集索引開始,而後是後面的操做纏繞運算-Table Spool
注意每一個運算符旁邊有一個百分比,這個值表值這個運算在整個執行過程當中所佔的資源百分比,這個值只是優化器估計的值。SQL語句的優化工做應該放在那些所佔的百分比比較大的操做上面。當把鼠標放上去的時候,會有一個換色的提示框。有一個值是Estimated Subtree Cost。最上方,最做坊的運算時整個運算的資源開銷。如圖2
圖2
注意這些值只是優化器估計出的值,優化器會使用這個值來和其餘的估計值做比較進而選擇出一個最優的執行計劃。
另一個比較好的地方時你能夠同時生成多個語句的執行計劃,進而對他們進行比較。例以下面的語句:
--1
SELECT custid, orderid, orderdate, empid, filler
FROM dbo.Orders AS O1
WHERE orderid =
(SELECT TOP (1) O2.orderid
FROM dbo.Orders AS O2
WHERE O2.custid = O1.custid
ORDER BY O2.orderdate DESC, O2.orderid DESC);
--2
SELECT custid, orderid, orderdate, empid, filler
FROM dbo.Orders
WHERE orderid IN
(
SELECT
(SELECT TOP (1) O.orderid
FROM dbo.Orders AS O
WHERE O.custid = C.custid
ORDER BY O.orderdate DESC, O.orderid DESC) AS oid
FROM dbo.Customers AS C
);
--3
SELECT A.*
FROM dbo.Customers AS C
CROSS APPLY
(SELECT TOP (1)
O.custid, O.orderid, O.orderdate, O.empid, O.filler
FROM dbo.Orders AS O
WHERE O.custid = C.custid
ORDER BY O.orderdate DESC, O.orderid DESC) AS A;
--4
WITH C AS
(
SELECT custid, orderid, orderdate, empid, filler,
ROW_NUMBER() OVER(PARTITION BY custid
ORDER BY orderdate DESC, orderid DESC) AS n
FROM dbo.Orders
)
SELECT custid, orderid, orderdate, empid, filler
FROM C
WHERE n = 1;
他們的 查詢結果是同樣的,可是執行計劃是不一樣的。在每一個執行計劃的開頭有一個百分比指示這個語句在全部的語句所佔的開銷的百分比。在這個例子中咱們能夠看到第一個語句的比例是37%,第二個語句的比例是19%,第三個是30%,第四個是14%。從這個結果咱們能夠粗略的認定第四個語句的效率要高一些。
當把鼠標放在運算符上面的時候會有一個黃色的提示框如圖4
圖4
在這個提示框中有下面的一些度量信息:
選中一個操做符,按下F4鍵,能夠查看更加詳細的信息。
文本格式的執行計劃
能夠經過設置以文本格式查看執行計劃。設置SHOWPLAN_TEXT選項能夠達到這個目的,以下:
SET SHOWPLAN_TEXT ON;
SELECT orderid, custid, empid, shipperid, orderdate, filler
FROM dbo.Orders WHERE orderid = 280885;
查看執行計劃(CTRL+L)獲得下面的結果:
(1 row(s) affected)
StmtText
-----------------------------------------------------------------------------------------------------
SELECT orderid, custid, empid, shipperid, orderdate, filler
FROM dbo.Orders WHERE orderid = 280885;
(1 row(s) affected)
StmtText
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|--Nested Loops(Inner Join, OUTER REFERENCES:([Uniq1002], [Performance].[dbo].[Orders].[orderdate]))
|--Index Seek(OBJECT:([Performance].[dbo].[Orders].[PK_Orders]), SEEK:([Performance].[dbo].[Orders].[orderid]=[@1]) ORDERED FORWARD)
|--Clustered Index Seek(OBJECT:([Performance].[dbo].[Orders].[idx_cl_od]), SEEK:([Performance].[dbo].[Orders].[orderdate]=[Performance].[dbo].[Orders].[orderdate] AND [Uniq1002]=[Uniq1002]) LOOKUP ORDERED FORWARD)
(3 row(s) affected)
(1 row(s) affected)
分析這個執行計劃,從內層的分支到外層分支,從上到下。可是在這裏咱們只能看到運算符的名字和參數。運行下面的語句關閉這個選項:
SET SHOWPLAN_TEXT OFF;
若是想獲得更加詳細的執行計劃信息,使用SHOWPLAN_ALL選項查看執行計劃,STATISTICS PROFILE選項查看具體的某一個執行計劃。SHOWPLAN_ALL將執行計劃的信息寫入到一個表中,其中包含的一些估計的值有:StmtText, StmtId, NodeId, Parent, PhysicalOp, LogicalOp, Argument, Defi nedValues,EstimateRows, EstimateIO, EstimateCPU, AvgRowSize, TotalSubtreeCost, OutputList,Warnings, Type, Parallel, and EstimateExecutions。
經過下面的語句打開這個選項:
SET SHOWPLAN_ALL ON;
運行下面的語句:
SELECT orderid, custid, empid, shipperid, orderdate, filler
FROM dbo.Orders WHERE orderid = 280885;
獲得的結果以下圖5:
圖5
運行下面的語句關閉選項:
SET SHOWPLAN_ALL OFF;
STATISTICS PROFILE選項會產生一個實際的計劃。設置這個選項爲ON的時候顯示的結果和設置SHOWPLAN_ALL爲ON差很少,不過多了兩個屬性Rosw和Executes,表示實際的行數和運行行數。
語句以下:
SET STATISTICS PROFILE ON;
SELECT orderid, custid, empid, shipperid, orderdate, filler FROM dbo.Orders WHERE orderid = 280885;
取消設置:
SET STATISTICS PROFILE OFF;
XML格式的執行計劃
若是想用本身的代碼來描述執行計劃或者把執行計劃發送給客戶或者同事,你會發現使用文本格式的信息很不方便。SQL Server 2008容許容許返回XML格式的執行計劃內容,這很是利於使用應用程序代碼處理。打開使用SQL Server 2008產生的xml格式的執行計劃會顯示成圖形結果,後綴是.sqlplan。
打開這個選項的代碼以下:
SET SHOWPLAN_XML ON;
運行語句
SELECT orderid, custid, empid, shipperid, orderdate, filler FROM dbo.Orders WHERE orderid = 280885;
運行結果以下圖6:
圖6
點擊這個xml文件,圖形格式的執行計劃以下圖7:
圖7
使用下面的語句關閉選項:
SET SHOWPLAN_XML OFF;
爲了避免影響其餘語句的輸出效果建議使用相似下面的代碼來查看效果:
SET STATISTICS XML ON;
GO
SELECT orderid, custid, empid, shipperid, orderdate, filler FROM dbo.Orders WHERE orderid = 280885;
GO
SET STATISTICS XML OFF;
能夠看出XML格式的執行計劃提供了最友好的查看形式。
本文轉載自:http://www.cnblogs.com/tylerdonet/archive/2011/11/17/2253090.html