我如何确定哪些函数和 sql 过程导致主机服务器上 cpu 使用率过高

How can I identify which functions and sql procedures are causing high cpu usage on the host server

我有一个 c#/asp.net 网络应用程序(非 mvc),它有一些页面使用存储过程和视图多次访问 sql 数据库。 该应用程序现在有 5-10 个用户,主机通知我它导致服务器上的 95%+ cpu 使用率。

我的问题是,我如何确定哪些 functions/procedures/threads 导致高 cpu 使用,以便我可以缓存或优化它们? 请注意,主机不允许我访问任何服务器日志、统计信息或服务器系统数据库表,只能访问我的应用程序的数据库,这让我很头疼!

在本地部署应用程序并进行诊断。

如果您的应用程序可以阻塞服务器,它很可能也会杀死您的机器。

如果您从应用程序调用存储过程:

在您的应用程序上添加详细跟踪日志的选项(只有当您想要按照您的描述检查场景时才会启用它)。 跟踪时间,cpu ...对于您怀疑导致问题的每种方法 (如果您无法获取日志文件,请将时间追溯到您的数据库)。 从你方法的函数中你可以找到存储过程

您可以使用 SqlProfiler 来跟踪任何 SQL 过程、函数等的性能和行为。

您可以检查一下:SqlProfiler 因为它是一个非常有用的工具,它确实帮助我提高了 sql 存储过程的性能。

您将 运行 您的应用程序,但在此之前转到您的 sql 分析器并将其配置为仅侦听所需的事件,例如 'procedure completed' 和 select 您的过滤条件,例如您的数据库或执行用户,然后当您在您的应用程序中执行与数据库相关的任何操作时,探查器将对其进行跟踪和分析。

您可以查看它的使用步骤here

关于与数据访问无关的 C# 函数,您可以使用秒表 class 来衡量它的性能以计算它的执行时间:

var watch = Stopwatch.StartNew();
// the code that you want to measure comes here
watch.Stop();
var elapsedMs = watch.ElapsedMilliseconds;

或者你可以Analyze Performance While Debugging in Visual Studio 2015

Sql 如前所述,Profiler 是您最好的选择。但是,我认为您需要 SQL 服务器的开发人员版本/工具才能使用它。

通常情况下,Sql 服务器将花费很长时间来加载和/或使用高 CPU 如果它继续进行 table 扫描。

向 table 添加索引会有所帮助。 您还应该检查是否意外错过了为 table 创建主键。

以防万一,您认为某些字段可能是唯一的 - 然后适当地指定唯一约束。例如,客户 table 中的电子邮件地址字段可能是唯一的。

此外,尽量避免在 nvarchar 字段上使用 "like"。如果您有 xml 个字段,请查看是否可以将最重要的字段单独存储在一列中。例如,在我工作的 Sql 服务器中,唯一的 "id" 字段之一位于 XML 列中 - 使 Sql 查询变慢。

您需要分别分析 .NET 代码和 SQL。我将处理 SQL 部分。

这是 Pinal Dave's query 的修改版本,它使用 sys.dm_exec_query_stats 查找最近的昂贵查询。我已经对其进行了调整以包括向您展示瓶颈的热路径。查询计划将帮助您进一步分解它。

SELECT TOP 50
  st.text AS [SQL Definition]
, SUBSTRING(
    st.text,
    qs.statement_start_offset / 2 + 1,
    ( CASE
        WHEN qs.statement_end_offset = -1 
        THEN LEN(CONVERT(NVARCHAR(MAX), st.text)) * 2 
        ELSE qs.statement_end_offset
      END - qs.statement_start_offset ) / 2
  ) AS [Hot Path]
, qs.execution_count AS [Execution Count]
, qs.total_worker_time / 1000000 AS [Total CPU (s)]
, (qs.total_worker_time / 00000) / qs.execution_count AS [Average CPU (s)]
, qs.total_elapsed_time / 1000000 AS [Total Time (s)]
, qs.total_logical_reads / qs.execution_count AS [Average Logical Reads]
, qs.total_logical_writes / qs.execution_count AS [Average Logical Writes]
, qs.total_physical_reads / qs.execution_count AS [Average Physical Reads]
, ISNULL(qp.query_plan, '') AS [Query Plan]
  FROM sys.dm_exec_query_stats AS qs WITH (NOLOCK)
 CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS st
 CROSS apply sys.dm_exec_query_plan (qs.plan_handle) AS qp
 ORDER BY [Total CPU (s)] DESC

这显然只是一个起点,但如果您的问题是由于查询效率低下或缺少索引造成的,它会为您指明正确的方向。