這篇文章我想談下SQL Server里一個非常重要的性能調優話題:重編譯(Recompilations) 。當你執行非常簡單的存儲過程(使用臨時表)時,就會發生。今天我想奠定SQL Server里重編譯的基礎,它們為什么會發生,下篇文章我會向你展示通過不同方式重寫你的存儲過程避免重編譯。
什么是重編譯?在我談SQL Server里重編譯細節前,首先來看看下面一個很簡單存儲過程。
1 CREATE PROCEDURE DemonstrateTempTableRecompiles 2 AS 3 BEGIN 4 CREATE TABLE #TempTable 5 ( 6 ID INT IDENTITY(1, 1) PRIMARY KEY, 7 FirstName CHAR(4000), 8 LastName CHAR(4000) 9 )10 11 INSERT INTO #TempTable (FirstName, LastName)12 SELECT TOP 1000 name, name FROM master.dbo.syscolumns13 14 SELECT * FROM #TempTable15 16 DROP TABLE #TempTable17 END18 GO
從代碼里可以看出,這個存儲過程并沒有什么特殊。第1步我們創建臨時表,然后臨時表里會插入一些記錄,最后用簡單的SELECT語句獲取插入的數據。在SQL Server里,像這樣的代碼你可能謝了上百次,甚至上千次。
接下來我們用SQL Server Profiler跟蹤下重編譯事件。點擊【工具】->【SQL Server Profiler】。輸入登錄密碼后,會彈出【跟蹤屬性】窗口。點擊【事件選擇】,勾選【顯示所有事件】,然后在事件列表里勾選【Stored Procedures】下列事件:
點擊【運行】開始跟蹤。在我們創建存儲過程后,我們運行存儲過程。
1 EXEC DemonstrateTempTableRecompiles
從上圖可以看到,我們在執行存儲過程時,發生了2次重編譯。
重編譯意味這SQL Server在運行執行計劃時,對執行計劃進行了重編譯。這會帶來額外的CPU開銷,最后減少服務器工作的吞吐量。但現在的問題是,為什么這些重編譯會發生?SQL Server執行重編譯主要是在下列2種情況發生:
在剛才執行的存儲過程里,因為這2個情況我們觸發了重編譯。我們再來看下剛才的存儲過程,第1步我們建立了臨時表,當我們在TempDb里建立臨時表時,你就改變了你的數據庫架構,因為這個原因第1個重編譯發生了。
在臨時表創建后,你插入了一些記錄。因此SQL Server需要去更新臨時表聚集索引的統計信息——聚集索引是由SQL Server通過主鍵(PRIMARY KEY)創建。1個簡單的存儲過程就引起了SQL Server里2個重編譯。哇噢~~~~~
小結重編譯會給臨時表帶來巨大的性能負荷。另一方面,臨時表有準確的統計信息幫助查詢優化器生成更好性能的執行計劃。因此,當你處理大量數據時,使用臨時表才是正確選擇。對于小量數據,重編譯引起的CPU負荷,比通過統計信息獲得性能提升的CPU負荷會高很多。
下篇文章,我會為你介紹表變量(Table Variables),我們會看到使用表變量如何避免重編譯的副作用——還有它們帶來的其它性能問題。請繼續關注!
附:SQL Server 2014的童鞋可以使用下列腳本通過擴展事件(Extended Event)跟蹤重編譯事件。
1 CREATE EVENT session [TrackRecompiles] ON SERVER 2 ADD EVENT sqlserver.sql_statement_recompile 3 ( 4 ACTION 5 ( 6 sqlserver.plan_handle, 7 sqlserver.sql_text 8 ) 9 ) 10 ADD TARGET package0.event_file(SET filename = N'c:/temp/TrackRecompiles.xel')11 WITH12 (13 MAX_MEMORY = 4096 KB,14 EVENT_RETENTION_MODE = ALLOW_SINGLE_EVENT_LOSS,15 MAX_DISPATCH_LATENCY = 30 SECONDS,16 MAX_EVENT_SIZE = 0 KB,17 MEMORY_PARTITION_MODE = NONE,18 TRACK_CAUSALITY = OFF,19 STARTUP_STATE = OFF20 )21 GO22 23 -- Start the Event Session24 ALTER EVENT SESSION TrackRecompiles25 ON SERVER26 STATE = START27 GO
新聞熱點
疑難解答