Rad*_*hiu 4 sql-server stored-procedures sql-server-2008-r2 dmv
我正在尝试编写查询以查找有关特定存储过程的查询统计信息和查询计划的信息,但我无法找到正确的 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
Run Code Online (Sandbox Code Playgroud)
但是这个查询不返回任何信息。理想情况下,我会st.text like
用类似的东西替换条件object_name(procedure_id) = 'myProcedure'
,但我找不到正确的方法。
有没有更好的方法来做到这一点?
我可以WHERE
用 a替换子句中的条件,qs.sql_handle = 0x000004004040400..etc.
但如何找出sql_handle
程序的条件?(此信息未在sys.objects
或 中找到sys.procedures
)。
任何信息都非常感谢。
更新:
我已经exec myProcedure ...
在测试环境中执行了过程 ( ),现在它由上述查询返回,因此我可以获得计划句柄以使用where sql_handle = 0x0034300..
,但我想在生产中从上面运行相同的查询,而无需在生产中运行该过程(只是为了找出它的计划句柄)。
这就是我尝试以这种方式编写查询的原因,以获取基于名称的信息,而不是sql_handle
(只是因为在 prod 中我不知道它的内容是什么sql_handle
)。
鉴于sys.dm_exec_query_stats
DMV 返回整个实例的数据,您需要能够跨所有数据库获取对象架构和名称信息。ST.objectid = OBJECT_ID(N'dbo.ProcedureName')
正如所建议的那样,使用容易出错,因为它只会解析与执行查询的数据库相关的名称:
NULL
,这将过滤掉所有行。object_id
值,但也可能指向不同的对象并可能返回一个或多个不正确的对象行。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')
Run Code Online (Sandbox Code Playgroud)
但是,我更喜欢使用OBJECT_NAME和OBJECT_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]
Run Code Online (Sandbox Code Playgroud)
然后您将更新您的查询以包含以下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
Run Code Online (Sandbox Code Playgroud)