Dus*_*tin 10 sql-server memory database-internals sql-server-2012 buffer-pool
我的问题是 SQL Server 如何处理需要将比可用空间更多的数据量拉入缓冲区缓存的查询?此查询将包含多个连接,因此磁盘上不存在此格式的结果集,它需要编译结果。但即使在编译之后,它仍然需要比缓冲区缓存中的可用空间更多的空间。
我举一个例子。假设您有一个 SQL Server 实例,它有 6GB 的可用缓冲区缓存空间。我运行具有多个连接的查询,读取 7GB 的数据,SQL Server 如何能够响应此请求?它是否将数据临时存储在 tempdb 中?它失败了吗?它是否只从磁盘读取数据并一次编译段?
此外,如果我尝试返回 7GB 的总数据会发生什么,这是否会改变 SQL Server 处理它的方式?
我已经知道有几种方法可以解决这个问题,我只是好奇 SQL Server 在按规定运行时如何在内部处理此请求。
此外,我确信该信息存在于某处,但我一直没有找到它。
Han*_*non 13
根据需要将页面读入内存,如果没有可用内存,则将最旧的未修改页面替换为传入页面。
这意味着如果您执行的查询需要的数据超出内存的容量,许多页面将在内存中的寿命非常短,从而导致大量 I/O。
您可以通过查看 Windows 性能监视器中的“页面预期寿命”计数器来查看此效果。查看https://sqlperformance.com/2014/10/sql-performance/knee-jerk-page-life-expectancy有关该计数器的一些详细信息。
在评论中,您具体询问了当查询结果大于可用缓冲区空间时会发生什么。举一个最简单的例子,select * from some_very_big_table;
假设表是 32GB,max server memory (MB)
配置为 24GB。将所有 32GB 的表数据一次一个地读入页缓冲区中的页中,并锁存,格式化为网络数据包,并通过网络发送。这是逐页发生的;你可以同时运行 300 个这样的查询,假设没有发生阻塞,每个查询的数据将被读入页面缓冲区空间,一次一个页面,并以客户端可以最快的速度发送到线路上请求和消费数据。一旦来自每一页的所有数据都发送到线路上,该页就会被解锁,并且很快就会被磁盘中的某个其他页替换。
在更复杂的查询的情况下,例如从多个表聚合结果,页面将完全按照查询处理器的要求被拉入内存。如果查询处理器需要临时工作空间来计算结果,它会在编译查询计划时预先知道这一点,并将从SQLOS请求工作空间(内存)。SQLOS 将在某个时候(假设它没有超时),将该内存授予查询处理器,此时查询处理将恢复。如果查询处理器在估计要从 SQLOS 请求多少内存时出错,它可能需要执行“溢出到磁盘”操作,其中数据以中间形式临时写入 tempdb。已写入 tempdb 的页面将在写入 tempdb 后解锁,以便为其他页面读入内存腾出空间。最终查询过程将返回存储在 tempdb 中的数据,使用闩锁将这些数据分页到缓冲区中标记为空闲的页面中。
毫无疑问,我在上面的总结中遗漏了大量非常技术性的细节,但我认为这抓住了 SQL Server 如何处理内存中无法容纳的更多数据的本质。
我无法确定您的查询在这种情况下会做什么,但 SQL Server 有几个选项,具体取决于需要多少。
找出会发生什么的最好方法是在开发环境中创建场景并找出答案。