为什么查询会导致溢出到 tempdb?

And*_*y W 27 sql-server sql-server-2012

背景

我正在将 160gb 数据库从具有 48gb RAM 的 Win 2008 服务器上的 MSSQL 2008(标准)迁移到在具有 64gb RAM 的 Win 2012 上运行 MSSQL 2012(64 位网络版)的新服务器。旧服务器处于活动状态且负载不足;新服务器不在生产中。新服务器有 8 个 tempdb 文件(每个 4GB)。

问题

在新服务器上进行测试时,我看到许多查询中的步骤导致提到“操作员使用 tempdb 在执行期间溢出数据”的警报。我已经能够通过重写一些查询来避免排序,但这并没有真正解决这个问题。旧服务器上的相同查询不会导致溢出。我读过当 MSSQL 无法在内存中完成操作并且必须溢出/分页到 tempdb 时会发生溢出。我应该担心溢出吗?

例子

在此处输入图片说明

我已经在数据库上运行了 sp_updatestats,所以统计信息应该是最新的,但是您会注意到估计的行数和实际的行数之间存在一些差异。

内存问题

我为 64gb 中的 58 个 MSSQL 设置了最大内存设置。目前 MSSQL 已经消耗了大约 35gb 的内存,但工作集只有 682mb。旧服务器(尽管在生产中,处理负载)有 44gb 的内存提交给 MSSQL,其中 43.5gb 在其工作集中。

在此处输入图片说明

我不知道溢出是否与内存设置有关-有人有任何想法吗?MSSQL 目前有大量 RAM 可用,那么为什么它会溢出到 tempdb 以进行某些排序和哈希匹配?

Bre*_*zar 28

这里有几个不同的问题:

问:为什么之前的查询没有溢出?

确实如此,但 SQL Server Management Studio 在 SQL 2012 之前并未将此作为明显错误显示出来。这是一个很好的例子,说明了为什么在进行性能调整时,您必须比图形执行计划更深入。

问:为什么查询会溢出到磁盘?

因为 SQL Server 没有授予他们足够的内存来完成他们的操作。也许执行计划低估了所需的内存量,或者盒子处于内存压力之下,或者它们只是大查询。(请记住,SQL Server 将内存用于三件事 - 缓存原始数据页、缓存执行计划和用于查询的工作区。工作区内存最终相当小。)

问:如何减少溢出?

通过编写 sargable T-SQL 语句,拥有最新的统计信息,在服务器中放置足够的内存,构建正确的索引,并在事情没有按照预期的方式运行时解释执行计划。查看Grant Friitchey 的书 SQL Server Query Performance Tuning以获得所有这些的详细解释。