提前:抱歉问题的长度......无法在细节和简洁之间取得适当的平衡。
我们的 Web 应用程序的数据库服务器存在问题,其中应该(并且通常会)在很短的时间(< 10 毫秒)内运行的查询,在随机情况下,需要 1 到 30 秒的时间来执行 - 没有明显的图案。根据我们的分析器跟踪,其中一些甚至是“无所事事”的查询,例如"exec sp_reset_connection"
(通常在 0ms 内运行;观察到的峰值为 3~6s),"SET NO_BROWSETABLE ON"
等等。一些例子是:
SELECT * FROM [Localisation].[TimeZoneRule] WHERE [Name] = 'EU'
WhereTimeZoneRule
在 5 列中有大约 500,000 行。具有代理主键和Name
. 通常需要 0.97ms,在 11s 达到峰值。永远不会写入表(在上线之前预先填充)。Profiler 将其记录为占用 0-15 CPU、18-25 读取、0-1 写入(不知道为什么要写入)。
UPDATE [Core].[User] SET [LastUsed] = GETUTCDATE() WHERE Id = '<uid>'
WhereUser
在大约 10 列(其中之一是 Xml 列)上有大约 30,000 行。Id
是聚集的主键。表被定期写入和读取。通常需要 10~20ms,在 26s 达到峰值。Profiler 将其记录为占用 0 CPU、15-36 读取、0-1 写入。
INSERT INTO [Log].[Session] (ASPSessionId, Start, ClientAddress, ClientSoftware, ProxyAddress, ProxySoftware)
VALUES(<number>, GETUTCDATE(), '<ipv4address>', '<User agent string>', '<ipv4address>', '<proxy software name (if present)>')
其中Session
大约 8 列有大约 1,000,000 行。有一个代理主键(身份)和一个索引ASPSessionId
。表定期写入,但很少读取(仅由我们直接从 SSMS 读取)。通常需要15~150ms,5s达到峰值。我手头没有它的配置文件记录,但从内存来看,CPU 大约为 0,读取和写入分别在 0 到 100 之间。
我们使用的设置是镜像设置,以戴尔 2950 为原理(2 个 4 核至强 2.6、16Gb RAM)和戴尔 6850 作为镜像(4 个 HT Xeon 3.2、8Gb RAM)。两者都运行 SQL 2005 SP4 64 位。有问题的数据库不是特别大,大小约为 16Gb。主有 6 个 SAS 磁盘,分为 3 个 RAID-1 卷;一份用于 System + Page + TempDB,一份用于数据库的 MDF,一份用于事务日志 + 每小时日志备份 + 每日 DB 备份。我知道日志情况远不是最好的——就磁盘 IO(见下文)和数据安全而言。
到目前为止,我们认为我们已经消除了:
- 镜子。我们分离了服务器,并使用其中一个运行(然后切换到另一个),但性能问题仍然存在。
- 由于锁(*)而阻塞。
TimeZoneRule
永远不会被写入,并且据我估计,永远不应该对它有排他锁。此外,我们已经检查了跟踪,在许多情况下,“问题查询”是唯一运行的 - 唯一的其他活动是其他连接断开 - 索引不佳。由于读取和 CPU 的数据较低,这表明 SQL Server 正在有效地使用索引。
- 磁盘 IO。PerfMon 表示数据文件驱动器(但仅该驱动器)的一些奇怪数字 - 虽然数据读取/写入速率似乎很少超过 32KB/s,但当前磁盘队列长度在大约 45 秒的 2-5 秒内飙升至大约 215 -60 分钟间隔,没有固定模式。但是,这些与查询性能不佳的时间无关。其他两个驱动器 [system + page + tempdb] 和 [log + backups] 的磁盘队列长度永远不会超过 3。
(*) 我们尝试让分析器捕获与锁定获取相关的事件,但跟踪膨胀到无法读取的程度,更糟糕的是,Web 应用程序停止运行。
不是 DBA,我们的想法很快就会枯竭。谁能想到我接下来应该考虑看的任何东西或我愚蠢地错过的任何东西?