Sur*_*ish 4 sql-server-2008 sql-server memory cache buffer-pool
使用 SQL Server 2008 R2,供应商数据库中的主事务表与所有其他表相比非常庞大,大约有 14 个索引。其中一些索引不会在我们的环境中使用,但我们无法删除它们。这不是问题,这只是我们必须忍受的事情。
我的问题是为什么这些低读取或无读取索引中的一些似乎正在使用内存 - 比同一个大表上经常使用的其他索引更多。我原以为大部分缓冲区缓存都会用于频繁读取的对象。这些索引上发生的唯一事情是写开销。
例如,这些低读取索引中的一个分配了大约 2 GB 的内存(索引总大小的 58%),另一个分配了 1.7 GB 的内存(其大小的 27%)。同时,规模庞大且使用良好的聚集索引本身只有 4 个演出(其大小的 2%)。具有大量读取的不同 NC 索引在缓冲区缓存中只有 100 MB(其大小的 5%)。
查看物理统计数据,我可以看到碎片非常糟糕。从该表上的所有写入和非顺序插入可以理解这一点。不过,我不确定它是否与内存使用有关。
查看这些索引的操作统计数据也很有趣。
我意识到这是一个抽象的问题,我没有提供很多实际的统计数据。我只是好奇 SQL Server 如何做出这些缓冲区缓存使用决策,并想知道是否有人理解它。
Sql Server 的缓冲池是一个很棒的东西。它足够聪明,可以以相当聪明的方式处理各种情况。下面是几个示例,显示缓冲池行为乍一看似乎很奇怪,但实际上相当聪明。
考虑在具有 64 GB 内存可用于缓冲池的服务器上的 400 GB 聚集索引。如果查询扫描整个 400 GB 的索引,查询完成后索引应该使用多少缓冲池?
可能不是很多。 如果 Sql Server 主动缓存它访问的所有数据,那么它在扫描期间读取的最后 50GB 可能在内存中。但是,下次运行相同的查询时,该 50GB 没有用,因为 Sql 必须从磁盘读取前 350GB,然后才能读取到最后 50GB。这是一个足够常见的场景,Sql 可以智能地处理它。相反,所有中级索引页面更有可能与一些叶页面一起被缓存。
我有一台有 512GB 内存的服务器,但它似乎从未使用过所有内存,或者它使用它......奇怪吗?
Sql Server 支持 NUMA。 在 NUMA(非统一内存访问)系统上,某些内存比其他内存更接近/更快。例如,一个 4 插槽系统可能有 4 个内存控制器(每个插槽 1 个)。CPU 访问与其相连的控制器上的内存比通过其他 CPU 的控制器访问内存更快。(我已经看到访问速度慢了 1.4-1.7 倍)。
Sql Server 知道这一点,并且更愿意在远程节点内存之前分配本地节点内存。由于请求可以在任何 cpu 上运行(它们通常不会在它们之间跳转)并因此在任何节点上分配内存,因此访问索引的第一个请求会将其页面缓存在本地内存中。在大多数情况下,您最终会得到相当均等的缓存页面分布,但是,每个节点都由 sql server 单独管理,因此有效地,您的 512 GB 实际上是四个 128 GB 的缓冲池。您可能会遇到节点 1 使用全部 128GB,节点 2 使用 80GB,并且页面从节点 1 被丢弃以腾出空间而节点 2 有大量可用空间的情况。
为什么我从索引中大量读取的缓存少于仅接收写入的索引?
一种可能的原因是检查点。 根据您的恢复间隔,数据更改发生后可能需要几分钟时间,然后检查点将页面写入数据文件(它已经在磁盘上的日志文件中)。在此期间,不能丢弃页面以在缓冲池中腾出空间。
除了设置大小之外,还有其他方法可以改变缓冲池的行为吗?
对缓冲池及其做出的决定没有太多控制权。这很好,因为您通常不需要调整它。观察“SQLServer:Buffer Manager”和“SQLServer:Buffer Node”的性能计数器可以深入了解缓冲池正在做什么,它的大小是否足够,您的 IO 子系统是否可以跟上检查点。
关于你提到的几个项目: