Sql-Server

查詢以查找特定儲存過程的計劃詳細資訊,按名稱搜尋

  • November 2, 2016

我正在嘗試編寫查詢以查找有關查詢統計資訊和特定儲存過程的查詢計劃的資訊,但我無法找到正確的 DMV 或查詢來查找特定儲存過程。

到目前為止,我有:

select
   qs.sql_handle
   , qs.statement_start_offset
   , qs.statement_end_offset
   , qs.plan_handle
   , execution_count
   , st.text
   , substring(st.text, (qs.statement_start_offset/2)+1,
       ((case qs.statement_end_offset
           when -1
               then datalength(st.text)
           else
               qs.statement_end_offset
           end - qs.statement_start_offset) / 2 + 1)) as [Filtered text]
   , qp.query_plan
from sys.dm_exec_query_stats as qs
   cross apply sys.dm_exec_sql_text (qs.sql_handle) as st
   cross apply sys.dm_exec_query_plan (qs.plan_handle) as qp
where st.text like '%myProcedure%'
order by qs.sql_handle
   , execution_count desc

但是這個查詢不返回任何資訊。理想情況下,我會st.text like用類似的東西替換條件object_name(procedure_id) = 'myProcedure',但我找不到正確的方法。

有更好的方法嗎?

我可以用 a 替換WHERE子句中的條件,qs.sql_handle = 0x000004004040400..etc.但我怎樣才能找到sql_handle過程的條件?sys.objects(在或 中找不到此資訊sys.procedures)。

非常感謝任何資訊。

更新:

我已經exec myProcedure ...在測試環境中執行了過程 (),現在它由上述查詢返回,因此我可以獲取計劃句柄以使用where sql_handle = 0x0034300..,但我想在生產中從上面執行相同的查詢,而不在生產中執行該過程(只是為了找出它的計劃句柄)。

這就是我嘗試以這種方式編寫查詢的原因,以獲取基於名稱的資訊,而不是sql_handle(只是因為在產品中我不知道它是什麼sql_handle)。

鑑於sys.dm_exec_query_statsDMV 返回整個實例的數據,您需要能夠跨所有數據庫獲取對象架構和名稱資訊。正如所建議的那樣,使用ST.objectid = OBJECT_ID(N'dbo.ProcedureName')很容易出錯,因為它只會解析相對於正在執行查詢的數據庫的名稱:

  1. 如果該數據庫中不存在對象名稱,那麼它將返回NULL,這將過濾掉所有行。
  2. 如果該數據庫中確實存在對象名稱,但您實際上希望該對象名稱來自不同的數據庫,那麼您將獲得一個可能object_id正確的值,但也可能指向不同的對象並可能返回一個或多個不正確的行。
  3. 如果object_id返回一個值,無論正確還是不正確,該特定值都可能存在於多個數據庫中,因此您可能會為不同數據庫中的不同對象返回多行。

至少,您需要提供一個完全限定的對象名稱(即三部分名稱)。但是,即使您確實使用OBJECT_ID(N'DatabaseName.SchemaName.ObjectName')了查詢,仍然有可能遇到上面提到的問題 #3,因為object_id即使是正確的,也可以存在於多個數據庫中。因此,您需要使用該DB_ID()函式來縮小到預期數據庫的第二個條件。

WHERE st.[objectid] = OBJECT_ID(N'DatabaseName.SchemaName.ObjectName')
AND   st.[dbid] = DB_ID(N'DatabaseName')

但是,我的偏好是使用OBJECT_NAMEOBJECT_SCHEMA_NAME函式,因為它們都接受database_id. 這樣做的好處是,SELECT當您不縮小到一個特定對象時,您可以在子句中使用它們,這樣您就可以看到 DMV 中所有行的對象名稱。它還允許在多個數據庫中過濾到相同的對象,當您在多個數據庫中具有相同的儲存過程並希望在所有數據庫中查看它的行時,這很有用,即使它object_id在這些數據庫中可能具有不同的值。

因此,您可以選擇將以下內容添加到SELECT子句中(我在交叉應用sys.dm_exec_sql_text到 DMV 時使用它,例如sys.dm_exec_requests等):

DB_NAME(st.[dbid]) AS [DatabaseName],
OBJECT_SCHEMA_NAME(st.[objectid], st.[dbid]) AS [SchemaName],
OBJECT_NAME(st.[objectid], st.[dbid]) AS [ObjectName]

然後您將更新您的查詢以具有以下WHERE子句:

WHERE OBJECT_NAME(st.[objectid], st.[dbid]) = N'my_proc_name'
AND   OBJECT_SCHEMA_NAME(st.[objectid], st.[dbid]) = N'dbo' -- or whatever schema
-- AND  DB_NAME(st.[dbid]) = N'DatabaseName' -- optionally narrow down to specific DB

引用自:https://dba.stackexchange.com/questions/143110