SQL Server 语句在 SQL Server 2008 R2 上间歇性变慢

14 performance sql-server-2008

在我们的一位客户身上,我们的应用程序一直存在一些性能问题。它是一个 .NET 3.5 Web 应用程序,它使用和更新 SQL Server 数据库上的数据。目前我们的生产环境由一台 Windows 2008 R2 机器作为前端和一个 SQL Server 2008 R2 集群在后端组成。我们的应用程序使用 COM+ 和 MSDTC 连接到数据库。

正在发生的事情是这样的:我们的最终用户有时会抱怨应用程序运行缓慢。有些页面需要比预期更长的时间来加载。在试图弄清楚发生了什么时,我设法在数据库端发现了一些可能导致性能下降的奇怪行为。我注意到有时有一些 SQL 语句需要更多的时间来运行,这超出了预期。我设法使用探查器跟踪(使用 TSQL_Duration 模板)来识别长时间运行的查询,从而识别出其中的一些语句(主要是调用我们的一些应用程序的存储过程)。

问题是,当我直接在 SQL Management Studio 上的数据库上运行这些存储过程时,有时它们确实需要很长时间(大约 7/8 秒),有时它们很快(不到 1 秒)。我不知道为什么会发生这种情况,这让我抓狂,因为 SQL 机器(4 核,32 GB)没有被任何其他应用程序使用,并且这些查询不应该花这么长时间运行。

不是 DBA 或 SQL Server 专家,我一直在尝试查看一些可以帮助我理解问题的东西。以下是我为尝试解决问题而采取的步骤以及我迄今为止发现的内容:

  • 应用程序调用的所有 TSQL 代码都编写在存储过程中。
  • 我在 SQL Server Profiler 上发现了一些长时间运行的查询,但是当我在 Management Studio 上运行这些查询时,它们要么需要很长时间才能运行(从 4 秒到 10 秒),要么运行得很快(不到 1 秒)。我正在使用参数中传递的相同数据运行完全相同的查询。这些查询主要是带有选择语句的存储过程。
  • 我尝试查看等待和队列统计信息以尝试确定是否有进程在等待某些资源。我运行了以下查询:

WITH Waits AS
    (SELECT
        wait_type,
        wait_time_ms / 1000.0 AS WaitS,
        (wait_time_ms - signal_wait_time_ms) / 1000.0 AS ResourceS,
        signal_wait_time_ms / 1000.0 AS SignalS,
        waiting_tasks_count AS WaitCount,
        100.0 * wait_time_ms / SUM (wait_time_ms) OVER() AS Percentage,
        ROW_NUMBER() OVER(ORDER BY wait_time_ms DESC) AS RowNum
    FROM sys.dm_os_wait_stats
    WHERE wait_type NOT IN (
        'CLR_SEMAPHORE', 'LAZYWRITER_SLEEP', 'RESOURCE_QUEUE', 'SLEEP_TASK',
        'SLEEP_SYSTEMTASK', 'SQLTRACE_BUFFER_FLUSH', 'WAITFOR', 'LOGMGR_QUEUE',
        'CHECKPOINT_QUEUE', 'REQUEST_FOR_DEADLOCK_SEARCH', 'XE_TIMER_EVENT',  'BROKER_TO_FLUSH',
        'BROKER_TASK_STOP', 'CLR_MANUAL_EVENT', 'CLR_AUTO_EVENT',     'DISPATCHER_QUEUE_SEMAPHORE',
        'FT_IFTS_SCHEDULER_IDLE_WAIT', 'XE_DISPATCHER_WAIT', 'XE_DISPATCHER_JOIN', 'BROKER_EVENTHANDLER',
        'TRACEWRITE', 'FT_IFTSHC_MUTEX', 'SQLTRACE_INCREMENTAL_FLUSH_SLEEP',
        'BROKER_RECEIVE_WAITFOR', 'ONDEMAND_TASK_QUEUE', 'DBMIRROR_EVENTS_QUEUE',
        'DBMIRRORING_CMD', 'BROKER_TRANSMITTER', 'SQLTRACE_WAIT_ENTRIES',
        'SLEEP_BPOOL_FLUSH', 'SQLTRACE_LOCK')
    )
SELECT
    W1.wait_type AS WaitType, 
    CAST (W1.WaitS AS DECIMAL(14, 2)) AS Wait_S,
    CAST (W1.ResourceS AS DECIMAL(14, 2)) AS Resource_S,
    CAST (W1.SignalS AS DECIMAL(14, 2)) AS Signal_S,
    W1.WaitCount AS WaitCount,
    CAST (W1.Percentage AS DECIMAL(4, 2)) AS Percentage,
    CAST ((W1.WaitS / W1.WaitCount) AS DECIMAL (14, 4)) AS AvgWait_S,
    CAST ((W1.ResourceS / W1.WaitCount) AS DECIMAL (14, 4)) AS AvgRes_S,
    CAST ((W1.SignalS / W1.WaitCount) AS DECIMAL (14, 4)) AS AvgSig_S
FROM Waits AS W1
    INNER JOIN Waits AS W2 ON W2.RowNum <= W1.RowNum
GROUP BY W1.RowNum, W1.wait_type, W1.WaitS, W1.ResourceS, W1.SignalS, W1.WaitCount,    W1.Percentage
HAVING SUM (W2.Percentage) - W1.Percentage < 95; -- percentage threshold
GO
Run Code Online (Sandbox Code Playgroud)

这是我发现的:

  • 在我使用 DBCC SQLPERF 重置统计信息后(大约 1 或 2 小时后),我最多的等待类型是 SOS_SCHEDULER_YIELD 和 WRITELOG
  • 随着时间的推移(执行大约 1 天后),数据库上发生最多的等待类型是 CXPACKET (67%) 和 OLEDB (17%),尽管它们的平均等待时间并不长。我还注意到,在 SQL Profiler 上识别出的运行时间较长的语句是对返回多个结果集(通常为 3 个)的存储过程的调用。这里可能存在并行问题吗?有什么方法可以尝试确定这是否是问题的原因?
  • 我在某处读到 OLEDB 等待可能是由调用 OLEDB 资源(如链接服务器)引起的。我们确实有一个链接服务器与索引服务机器 (MSIDXS) 连接,但是标识为长时间运行的语句都没有使用该链接服务器。
  • 我有更高的平均等待时间是 LCK_M_X 类型的等待(平均大约 1.5 秒),但与其他类型相比,这些等待类型不会经常发生(例如,64 LCK_M_X 等待 vs 10,823 CXPACKET 等待在同一时间段内)。
  • 我注意到的一件事是 MSDTC 服务没有集群。SQL Server 服务是群集的,但不是 MSDTC。会因此而影响性能吗?我们使用 MSDTC 是因为我们的应用程序使用企业服务 (DCOM) 来访问数据库,但服务器不是由我们安装和配置的,而是由我们的客户端安装和配置的。

任何人都可以帮助我更了解这些数据吗?任何人都可以帮助我了解可能发生的事情吗?我可以在服务器上做些什么来尝试解决问题吗?我应该与应用程序开发团队交谈吗?

San*_*ddy 4

感谢您对问题的详细解释(实际上是最好的问题之一)。

WRITELOG 是一种非常常见的等待类型,因此不必担心。查看指示 CPU 压力的 SOS_SCHEDULER_YIELD 以及 CXPACKET,可能肯定缺少一些索引,并且您可能从 OLTP 系统的查询中检索大量数据。我建议您查看缺失索引 DMV,看看是否有任何索引(几乎可以肯定会有不少)位于有问题的进程中。

http://sqlfool.com/2009/04/a-look-at-missing-indexes/

http://troubleshootingsql.com/2009/12/30/how-to-find-out-the-missing-indexes-on-a-sql-server-2008-or-2005-instance-along-with-the-create-index-commands/

也可以在 sqlblog.com 上查找 Jonathan Kehayias 关于此问题的帖子。

另外,看看参数嗅探。

http://sommarskog.se/query-plan-mysteries.html

http://pratchev.blogspot.com/2007/08/parameter-sniffing.html

这不是满足您需求的完整答案,而是一个很好的起点。如果您需要更多详细信息,请告诉我们。