我的问题是,SQL Server 需要很长时间才能为具有 TB 级 RAM 的实例增加内存使用率,而我们一直间歇性地等待 MEMORY_ALLOCATION_EXT,这会减慢我们的处理速度,直到 SQL Server 达到其最大内存。
我们有 SQL Server 2019 企业版的故障转移集群实例 (FCI),节点上有数 TB 的内存。在通常的用例中,我们只允许每个节点有 1 个 SQL Server 实例,因此我们将最大服务器内存设置为接近节点内存的约 85%,但我们也将最小服务器内存设置得相对较低,以防 SQL Server 故障转移到另一个节点,需要在减少内存占用的情况下联机才能继续前进。
我很清楚,如果我将最小内存设置得更高,SQL Server 将一次性消耗所有内存。原来 SQL Server 在启动时没有分配最小内存。- 我知道 SQL Server 会根据需要从操作系统动态消耗更多内存,最终它将达到最大服务器内存。
- 我知道运行大查询或提取大量数据的 DBCC checkdb 将迫使 SQL Server 从操作系统消耗更多内存。
是否有任何其他方法可以强制 SQL Server 快速增加其内存使用量?
SQL Server 不会将内存用于缓冲池(它的最大用途),直到它需要从存储中加载页面,因为它们被引用。除非您正在做一些奇怪的事情来使内存分配变慢[†],否则您的延迟不太可能是这样,而是读取它被分配以保存的数据。我怀疑在那些内存分配等待的同时,你有匹配的 IO 相关等待。
要强制 SQL Server 将内容加载到内存中,并因此在可用和需要时分配内存,请访问需要加载的内容。启动 SQL 实例后,运行只读工作负载,以便将应用程序的正常通用工作集加载到缓冲池中。
不要只是
SELECT * FROM HugeTable
因为这可能会加载不平衡的数据(而不是应用程序核心工作集),所以核心工作集仍然需要在下次访问时从磁盘/网络加载,这样您将拥有相同的 IO延误。此外,如果HugeTable
真的很大,SQL Server 可能会发现它并不完全适合,并且无论如何都不会费心将大量它保存在内存中[‡]。[†]在超载主机上的 VM 中运行,所以看起来像真实 RAM 的实际上是磁盘上的页面?!
[‡]在正常情况下,您不希望对大型对象进行意外的表/索引扫描以从内存中逐出其他所有内容。一个查询从一个对象中保留多少的限制是一种优化,以尝试阻止这种情况发生)。
不,这是不正确的,最小服务器内存与设置后 SQL Server 消耗它的速度无关。Min server memory 表示最小内存量(如果已消耗),在此之后,如果要求,SQL Server 在正常情况下不会释放低于此值的内存。一旦达到最小服务器值,SQL Server 将不会修剪其缓存并释放低于此值的内存。
是的正确,只是在某些条件下添加 SQl Server 也会消耗大于 max server memory 中指定的值的内存。您应该阅读内存管理指南
还有其他方法可以强制 SQL Server 在启动期间保留更多内存,这称为“大页面”。这是企业版功能,允许 SQL Server 在启动时快速保留一些空闲内存,SQL Server 服务帐户也应该具有锁定页面的内存特权,因为大页面的分配是由windows 操作系统的VirtualAlloc()函数完成的,操作系统应该有超过 8 GB RAM,如果自动满足这些条件,则启用大页面分配。一旦启用,它将在错误日志中显示如下
在 X64 系统上,内存的正常页面大小为 4 KB,但启用大页面时,大小将为 2 MB。另请注意,即使您未启用跟踪标志 834,引擎也会启用和使用 LargePageSupport。但不会为此使用太多内存,并且除非启用跟踪标志 834,否则不会使用缓冲池内存。请参阅共享的博客。