用于 UDF 性能统计的 MS SQL DMV - 如何找到前 10 个最差的 UDF

Posted

技术标签:

【中文标题】用于 UDF 性能统计的 MS SQL DMV - 如何找到前 10 个最差的 UDF【英文标题】:MS SQL DMVs for UDF performance stats - how to find top 10 worst UDFs 【发布时间】:2011-04-18 15:02:44 【问题描述】:

我听说在 Microsoft SQL Server 中有多种方法可以找到“最差”的存储过程:按执行次数、CPU 工作时间、队列等待时间等。

我正在寻找一种方法来找到最差(最慢/最常用)的 UDF —— 是否有 DMV 查询?

例如,来自Five DMV Queries That Will Make You a Superhero 的此查询返回按总工作时间计算的前 25 个缓存 SP,这实际上意味着 CPU 压力最昂贵的存储过程。

如何为 UDF 编写类似的内容?

SELECT TOP(25) p.name AS [SP Name], qs.total_worker_time AS [TotalWorkerTime], 
qs.total_worker_time/qs.execution_count AS [AvgWorkerTime], qs.execution_count, 
ISNULL(qs.execution_count/DATEDIFF(Second, qs.cached_time, GETDATE()), 0) AS [Calls/Second],
qs.total_elapsed_time, qs.total_elapsed_time/qs.execution_count 
AS [avg_elapsed_time], qs.cached_time
FROM sys.procedures AS p
INNER JOIN sys.dm_exec_procedure_stats AS qs
ON p.[object_id] = qs.[object_id]
WHERE qs.database_id = DB_ID()
ORDER BY qs.total_worker_time DESC OPTION (RECOMPILE);

【问题讨论】:

【参考方案1】:

试试这个。

将 sys.procedures 更改为 sys.sql_modules 进一步加入sys.objects 按sys.objects.type IN ('IF', 'TF', 'FN')过滤

上面的代码仅限于存储过程

注意:没有“sys.functions”

【讨论】:

【参考方案2】:

这是查找性能最差的 TOP 100 SQL 语句的另一种方法,其中包含这些语句的对象名称,例如存储过程、触发器和函数。这在上下文中运行,因此您需要将 SSMS 切换到要在其上运行的数据库,或者输入 USE DB 语句。此外,如果您重新启动数据库,DMV 统计数据将重置,因此它可能会返回“0”行...

SELECT TOP 100 [Object_Name] = object_name(st.objectid), creation_time, last_execution_time, total_cpu_time = total_worker_time / 1000, avg_cpu_time = (total_worker_time / execution_count) / 1000, min_cpu_time = min_worker_time / 1000, max_cpu_time = max_worker_time / 1000, last_cpu_time = last_worker_time / 1000, total_time_elapsed = total_elapsed_time / 1000 , avg_time_elapsed = (total_elapsed_time / execution_count) / 1000, min_time_elapsed = min_elapsed_time / 1000, max_time_elapsed = max_elapsed_time / 1000, avg_physical_reads = total_physical_reads / execution_count, avg_logical_reads = total_logical_reads / execution_count, execution_count, SUBSTRING(st.text, (qs.statement_start_offset/2) + 1, ( ( CASE statement_end_offset WHEN -1 THEN DATALENGTH(st.text) ELSE qs.statement_end_offset END - qs.statement_start_offset ) /2 ) + 1 ) as statement_text FROM sys.dm_exec_query_stats qs CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st WHERE Object_Name(st.objectid) IS NOT NULL AND st.dbid = DB_ID() ORDER BY db_name(st.dbid), total_worker_time / execution_count DESC

【讨论】:

【参考方案3】:

SQL Server 2016 及更高版本(和 SQL Azure)具有 DMV sys.dm_exec_function_stats:

返回有关标量函数的信息,包括内存中的函数 函数和 CLR 标量函数。不返回有关信息 表值函数,以及关于内联的标量函数 使用标量 UDF 内联。

SELECT 
    OBJECT_NAME(object_id) AS ScalarFunction, 
    execution_count,
    total_worker_time, 
    total_logical_reads, 
    total_elapsed_time,
    min_worker_time,  -- Note: microseconds
    max_worker_time,  -- Note: microseconds
    AvgWorkerTimePerExecution_microsecs = total_worker_time / (1. * execution_count)
FROM 
    sys.dm_exec_function_stats WITH(NOLOCK) 
WHERE 
    database_id = DB_ID()
    AND OBJECT_NAME(object_id) IS NOT NULL
ORDER BY 
    total_worker_time DESC 
OPTION(RECOMPILE); 

注意:所有时间指标均以微秒为单位

【讨论】:

以上是关于用于 UDF 性能统计的 MS SQL DMV - 如何找到前 10 个最差的 UDF的主要内容,如果未能解决你的问题,请参考以下文章

使用DMV,诊断和调优DB性能。

sql server DMV汇总

MS SQL Server 中的标量 UDF 在查询中仅返回一个值

sql server使用DMV排查系统异常

sqlserver dmv 动态管理视图

将 UDF 从 MS SQL Server 移植到 MySQL 会引发异常不正确的双精度值