And*_*sch 11 performance sql-server service-broker
我们正忙于对我们在 .NET 4.0 中开发并在后台运行 SQL Server 2008 R2 的 OLTP 系统进行负载测试。系统使用 SQL Server Service Broker 队列,它们的性能非常好,但我们在处理时遇到了一个特殊的趋势。
SQL Server 以极快的速度处理请求 1 分钟,然后增加约 20 秒的磁盘写入活动。下图说明了这个问题。

Yellow = Transactions per second
Blue = Total CPU usage
Red = Sqlsrv Disk Write Bytes/s
Green = Sqlsrv Disk Read Bytes/s
Run Code Online (Sandbox Code Playgroud)
在故障排除期间,我们尝试了以下方法,但模式没有任何重大变化:
似乎 SQL Server 可能正在建立其缓存并以特定的时间间隔将其写入磁盘,但我无法在网上找到任何支持该理论的内容。
接下来,我计划将解决方案转移到我们的专用测试环境中,看看我是否可以复制该问题。在此期间的任何帮助将不胜感激。
更新 1 根据要求,附上一张图表,其中包括Checkpoint Pages/Sec、Page Life Expectancy和一些磁盘延迟计数器。

看起来好像检查点(浅蓝线)是我们观察到的性能下降(黄线)的原因。^
磁盘延迟在处理过程中保持相对一致,页面预期寿命似乎没有任何明显影响。我们还调整了 SQL Server 可用的 ram 量,这也没有太大影响。将恢复模型从 更改SIMPLE为FULL也没什么区别。
更新 2 通过如下更改“恢复间隔”,我们设法减少了检查点发生的间隔:
EXEC sp_configure 'show advanced options',1
GO
RECONFIGURE
GO
EXEC sp_configure 'recovery interval', '30'
GO
RECONFIGURE
GO
EXEC sp_configure 'show advanced options',0
GO
RECONFIGURE
Run Code Online (Sandbox Code Playgroud)
我不确定这是否是不好的做法?
Rem*_*anu 11
其他人已经指出了罪魁祸首:SQL Server 在内存中(在缓冲池中)累积更新,并且只定期(在检查点)刷新它们。建议的两个选项(-k 和检查点间隔)是互补的:
但我没有回应只是为了反驳你收到的好评:)
不幸的是,您看到的是排队处理的一种非常典型的行为。无论您使用 Service Broker 队列还是选择使用表作为队列方法,系统都非常容易出现这种行为。这是因为基于队列的处理写入量很大,甚至比 OLTP 处理写入量更大。入队和出队原语都是写操作,几乎没有读操作。简而言之,与任何其他工作负载,甚至是 OLTP(即TPC-C 之类的工作负载)相比,队列处理将生成最多的写入(= 最多的脏页和最多的日志)。
非常重要的是,队列工作负载的写入遵循插入/删除模式:插入的每一行都很快被删除。这对于区分插入繁重 (ETL) 工作负载的仅附加模式很重要。您基本上是在为幽灵清理任务提供一顿丰盛的饭菜,而且您可以轻松超越它。想想这意味着什么:
是的,这确实意味着您最终可能会在三个不同的 IO 请求中,针对您处理的每条消息(最坏的情况)将页面写入磁盘 3 次。这也意味着检查点的随机 IO 将是真正随机的,因为页面的写入点将在两个检查点之间再次被那些移动磁头访问(相比许多 OLTP 工作负载倾向于将写入分组到一些“热点”,不是排队……)。
所以你有这三个写点,竞相一次又一次地将同一个页面标记为脏。那是在我们考虑任何页面拆分之前,由于插入键顺序,队列处理也可能容易发生。相比之下,“典型”的 OLTP 工作负载具有更加平衡的读/写比率,并且 OLTP 写入分布在插入/更新/删除之间,通常更新(“状态”更改)和插入占据大部分份额。队列处理写入专门插入/删除,根据定义,50/50 拆分。
一些后果如下:
我的建议有 3 个字母:S、S 和 D。将您的 MDF 移动到可以处理快速随机 IO 的存储中。固态硬盘。如果你有钱,Fusion-IO。不幸的是,这是使用更便宜的 RAM 无法解决的症状之一......
编辑:
正如 Mark 指出的那样,您有两个逻辑磁盘由一个物理磁盘支持。也许您尝试遵循最佳实践并拆分 D: 上的日志和 C: 上的数据,但可惜无济于事,C 和 D 是同一个磁盘。在检查点之间,您实现了连续吞吐量,但一旦检查点启动,磁盘磁头就开始移动,您的日志吞吐量会崩溃,从而降低整个应用程序的吞吐量。确保将 DB 日志分开,以免受到数据 IO 的影响(单独的磁盘)。