我的服务器正在运行 SQL Server 2016。该环境的工作负载相当高,全天有大量写入事务和读取数据。我有一种预感,服务器没有配置足够的内存,我想深入研究一下,看看是不是这样。确定服务器上可用内存量是否以及产生多少争用的最佳方法是什么?
我确实查看了 DMV sys.dm_os_wait_stats,当按 waiting_tasks_count desc 排序时,前两种等待类型是“MEMORY_ALLOCATION_EXT”和“RESERVED_MEMORY_ALLOCATION_EXT”,比任何其他等待类型任务计数都大一个数量级。还有其他地方我可以检查内存压力或争用吗?
编辑:此服务器上所有数据库的总大小为 3 TB,具有大部分事务的主数据库为 2 TB,服务器上的 RAM 总量为 32 GB。
这里有几个 perfmon 计数器可以用作启动器。
Memory Grants Pending - 这是一个计数器,告诉您是否有任何查询等待内存授予(内存分配)。这实际上应该是 0。如果它始终超过这个值,那么你就有问题了。
页面预期寿命 - 这是页面在内存中停留的估计时间量(以秒为单位)。越高越好,但是有一个公式可以计算您的服务器的最小值实际上应该是多少。过去它至少是 300 秒,但这是一个古老的计算方法,现在应该是每 GB 100 秒。我在 SQL 星期六会话期间从 Richard Douglas 那里得到了这个,所以归功于他。他为 SentryOne 工作。小于该值表明分配的内存太少。还可以将此计数器与 Checkpoint pages/sec 结合使用。请注意,每个 NUMA 节点都有自己的 PLE 值(如果您的 SQL Server 上有多个 NUMA 节点)。SQL Server 开始将资源分配到分配的 8 个以上核心的(软)NUMA 节点中。
延迟写入/秒 - 当 SQL Server 遇到内存压力时,延迟写入进程会从缓存中清除旧页面。始终高于 20 是一个问题(也从 Richard Douglas 那里得到了这个)。但是,请将其与页面预期寿命结合使用。如果您看到较高的 PLE 以及延迟写入/秒的峰值,那么某些原因导致 SQL 从其缓存中删除页面并插入新页面。有关我家庭实验室的示例,请参见下面的屏幕截图。
我相信这里的一些专家对记忆文员了解更多,仍然在我的列表中进行更深入的研究,所以也许有人有一些额外的信息给你(我也非常感兴趣:-))。
编辑:如果您愿意,您还可以使用 sys.dm_os_performance_counters 通过查询即时获取它们。
2020 年 6 月 24 日编辑:
@JD 关于您 6 月 23 日的评论;由于@Dominique Boucher 和这篇文章的评论,我也深入挖掘了内存压力:https ://www.brentozar.com/archive/2020/06/page-life-expectancy-doesnt-mean-杰克和你应该停止看它/. 当我在邮箱里收到这个时,我笑了;也许他看到了这个帖子。:-) 这篇文章告诉我们不要再看它了。好吧,虽然布伦特肯定比我更有经验,但我认为我不能完全同意他永远不会看的说法。我在他的 sp_BlitzFirst 的上下文中理解了他的观点,单个查询使用最多 25% 的缓冲区缓存,它是一个滞后指标,等等。但对于趋势分析和历史,我仍然会查看 PLE 与 Lazy Writer。如果我想确定服务器是否随着时间的推移存在内存压力,这就是我将与等待内存授予结合使用的方法。此外,RedGate 和 Quest 的监控工具仍然使用它。现在@Dominique Boucher 说要查看 RESOURCE_SEMAPHORE 等待,我同意,但这很可能与未决内存授予的数量一致(您可以轻松地向 perfmon 注册)。如果您有一个恒定的内存授予队列(它与 FIFO 队列一起使用),那么您确实有内存压力。
作为参考,这是针对这个宇宙中某个系统的 Lazy Writer(32 GB 内存,1 TB 数据库,虽然工作负载的类型也很重要)。黄色是batch requests p/s,10表示一个1000,可以看出肯定不是空闲的。
这也是我的家庭实验室关于内存授予与 RESOUCE_SEMPAPHORE 等待的快照(我还看到我突出显示了 tempdb 写入,这就是 david 所说的,内存太少,所以溢出到 tempdb):
现在,看看你的性能计数器,我认为你肯定有内存问题。我是说; 有些东西不断地迫使 SQL Server 从缓冲区缓存中删除页面。如果这将是一次,好的,但它似乎一直忙于这样做......但是,我希望看到它们与 PLE 相比。这可以清楚地表明存在内存压力(随着时间的推移,我仍然这么认为)。其次,您还想查看未决的内存授予。现在,我之前没有这么说,但回头看,我确实认为你想看看布伦特和多明克所说的等待统计数据。然而,随着时间的推移,这有点困难。等待统计信息是累积收集的,因此您需要先清除它们(我不喜欢),然后查看它们是否 RESOURCE_SEMAPHORE 加起来。
要清除等待统计信息:https ://learn.microsoft.com/en-us/sql/t-sql/database-console-commands/dbcc-sqlperf-transact-sql?view=sql-server-ver15
您也可以使用 sp_BlitzFirst 对其进行监控,但这只是您运行它时的快照。sp_BlitzFirst(或我记不起的 sp_Blitz)有一个选项可以定期将其记录在表中,因此您也可以查看它。或者只是以其他方式自己查询 dm_os_wait_stats 也可以。一般来说,我个人的偏好是随着时间的推移收集数据来分析这一点。我使用来自 Steve Stedman 的 Database Health Monitor 执行此操作:databasehealth.com。我的家庭实验室的屏幕截图:
这样,您可以更好地监控等待统计信息,尽管这会花费您一点点资源。
如果您有 SQL Server 2017 或更高版本(我们的环境中还没有),那么您也可以使用查询存储。从 SQL Server 2017 开始,查询存储还记录等待统计信息(这是一个可配置的选项)。不过要小心,我读过 Query Store 让非常繁忙的服务器瘫痪的故事(您可以使用等待统计信息进行监控:-P)。当然,在 prod 中实现功能之前,您应该始终进行测试。我们确实使用它,而且效果很好,但是我们有 2016 年,所以我们确实错过了等待统计选项:-(。
顺便一提; 我的策略是收集信息(性能,如果可能,等待统计信息),如果你认为内存压力升级 RAM(如果是一个非常容易的 VM),然后收集性能指标并检查它们是否有所改善。有点简单,但后者经常被遗忘或做得不好。