使用 NUMA 扩展和收缩缓冲池

本主题介绍,在使用非一致性内存访问 (NUMA) 时,如何分配缓冲池中的内存页。使用此信息可以了解 SQL Server 使用 NUMA 的方式,并了解如何解释缓冲节点对象计数器。

内存分布

每个物理 NUMA 节点都有一个 SQL Server 内存节点。内存节点彼此独立地增长,但是会平均划分内存。为了显示 SQL Server 中的本地内存分布与外部内存分布,本主题使用的示例假定计算机的内存大小为 16 GB。包含 Windows 在内的其他应用程序已占用了各个节点上的一些内存,SQL Server 已经为缓冲池外部的进程分配了一些内存,现在,SQL Server 可以为缓冲池分配的内存只有 10 GB。在四个物理 NUMA 节点 N0、N1、N2 和 N3 之间,对缓冲池内存进行了划分,其中每个节点的本地可用内存分别为:

  • N0 – 1 GB

  • N1 – 3 GB

  • N2 – 3 GB

  • N3 – 3 GB

在上述配置中,所有节点最终分配并使用 2.5 GB 内存;但是,节点 N0 将用完它自己的 1.0 GB 内存并使用其他节点上的 1.5 GB 内存。

启动时的内存分配

使用 NUMA 时,即使初始可用内存在节点之间的分布不均匀,SQL Server 也能够以可与非 NUMA 系统比拟的速度从操作系统中接收内存。缓冲池将尝试为每个节点获取尽可能多的本地内存;但是由于 Windows 当前没有从特定节点分配内存的 API,因此很难完成此操作。

当内存分配到 SQL Server 时,您可以观察到某些节点获得了许多来自其他 NUMA 节点的页(称为“外部页”)。但是,由于这些外部页可以被频繁地传输到所属节点并变为该节点的本地页,因此,不能在增长过程中使用这些页。当达到 max server memory 值时,一些节点便会拥有外部内存,但是一旦达到内存目标,缓冲池便会同等处理本地内存和外部内存。例如,在内存压力下,缓冲池不会努力尝试在释放本地内存页前释放外部内存页。

将内存限制到特定节点

如果已将 SQL Server 配置为在可用 NUMA 节点的子集上运行,则不会自动将缓冲池限制为这些节点上的内存。在这种情况下,可以使用 max server memory 选项限制缓冲池。有关 max server memory 的信息,请参阅服务器内存选项

从节点释放内存

使用 NUMA 时,会在 NUMA 节点之间平均划分 max server memorymin server memory 的值。例如,如果在具有四个节点的系统上将 max server memory 设置为 16 GB,则缓冲池将为每个节点分配 4 GB 内存。如果通过更改 affinity mask 设置使其中一个节点脱机,则将在剩余的节点上重新分布 max server memory 设置。例如,在先前的四个节点示例中,如果使两个节点脱机,则在剩余的节点上均匀分布已释放的 8 GB 内存。因为缓冲池可以使用外部页,所以当剩余节点上的内存不足时,可使用远程内存。如果您希望 SQL Server 不使用它不再在其上运行的节点的内存,则必须在使节点脱机后减小 max server memory 设置。

外部页

各节点在很大程度上彼此独立发挥作用。某个节点的所有内存分配和释放均使用与该节点相关的内存完成。但是,如果节点 N1 上运行的工作线程需要访问节点 N2 内存中的数据库页,则表示它要访问非本地内存。

观察缓冲池中的本地内存与外部内存

可以通过查看 Buffer Node 对象来观察缓冲池。SQL Server 的缓冲池中的总内存显示为 Buffer Manager 对象的**“目标页数”的计数器。缓冲池中用于每个节点的内存显示为 Buffer Node 对象的“目标页数”的计数器。其他节点的内存显示为“外部页数”**的计数器。有关详细信息,请参阅 SQL Server Buffer Node 对象SQL Server Buffer Manager 对象

每个节点自身内存的检查点

每个内存节点都有它自己的惰性编写器线程。此线程可同时针对隐式检查点和显式检查点进行调用。由于对称多处理 (SMP) 计算机仅有一个检查点线程,因此,在使用 NUMA 时,多个线程将导致检查点的速度增加。

表扫描行为

除非在 CPU 上对多个节点执行并行扫描,否则,对节点 N1 执行的表扫描仅填充与节点 N1 关联的内存。如果只对单个节点执行排他扫描,则仅使用该节点的缓冲区页。这有助于对**“应用程序”**的工作负荷进行分区。