天天看點

SQL Server如何定位自定義标量函數被那個SQL調用次數最多淺析

前陣子遇到一個很是棘手的問題,監控系統DPA發現某個自定義标量函數被調用的次數非常高,高到一個離譜的程度。然後在Troubleshooting這個問題的時候,确實遇到了一些問題讓我很是糾結,下文是解決問題過程的一點思索和嘗試,如果你有更好的思路和解決方法,也請多多指教。

DPA可以監控到該函數每小時被調用的次數,如下截圖所示:

SQL Server如何定位自定義标量函數被那個SQL調用次數最多淺析

那麼第一個問題來了。 <b>DPA如何監控擷取這個函數每小時執行多少次呢</b>? 其實這個很簡單, sys.dm_exec_query_stats視圖裡面有個字段execution_count 統計SQL的執行次數,但是它記錄的是計劃自上次編譯以來所執行的次數。那麼,我整點執行兩次結果的內插補點(execution_count的內插補點)就是一小時内的執行次數。

execution_count     Number of times that the plan has been executed since it was last compiled.(計劃自上次編譯以來所執行的次數。)

這個我們可以試驗一下,如下所示,在AdventureWorks2014,我們建立一個自定義标量函數,然後我們

SQL Server如何定位自定義标量函數被那個SQL調用次數最多淺析

DECLARE @ProductID INT;

SET @ProductID=897

SELECT DISTINCT ProductID, Sales.FetchProductOrderNum(ProductID) FROM Sales.SalesOrderDetail

WHERE ProductID=@ProductID

SET @ProductID=870

SQL Server如何定位自定義标量函數被那個SQL調用次數最多淺析

如上所示,假設一個小時内隻執行了上面兩個SQL,那麼我知道這個自定義函數被調用了 9378 - 4688 =4690次。 是以基于這種規則,就可以找出一小時内自定義函數的調用次數,當然其它資料庫對象也可以如此計算。

那麼接下來的問題,一個資料庫中有多腳本都調用了這個自定義标量函數,但是我怎麼判别、區分那個SQL腳本調用了自定義函數最多(或者能查出TOP 10 SQL語句),這個問題糾結了好久,查找了好多資料,均無法實作這個功能。

為什麼有這樣的需求呢? 因為,不能定位那個SQL調用的次數最多,我無法定位問題根源,我遇到的案例,發現有接近200個地方調用這個自定義函數,如果一個個去判斷分析、這個是個累死人的體力活,而且有些SQL非常不容易确定

會調用多少次,(例如有些是在臨時表上調用該函數, 有些條件是傳入的變量等等)。

SQL Server如何定位自定義标量函數被那個SQL調用次數最多淺析

我們來驗證一下我們上面測試的案例,如下所示, 你會看到本身Sales.FetchProductOrderNum這個自定義标量函數的調用次數才是最多的,是以如果按execution_count來統計,這個是完全不行的,例如其中一個SQL執行一次(ProductID=870),Sales.FetchProductOrderNum标量函數就要被調用好幾千次,而按照了邏輯讀(total_logical_reads或last_logical_reads)來分析,基本上就能定位到調用标量函數次數最多的SQL了。當然實際環境遠遠比這個測試案例複雜的多。

SQL Server如何定位自定義标量函數被那個SQL調用次數最多淺析