SQL Server 存储中间结果集

时间:2021-10-13 21:42:21

在SQL Server中执行查询时,有一些操作会产生中间结果集,例如:排序操作,Hash Join和Hash Aggregate操作产生的Hash Table,游标等,SQL Server查询优化器使用 Worktable 和 Workfile 存储中间结果集,对中间结果集执行后续操作,以响应用户的请求。

一,Spool 操作符

Spool的中文解释是假脱机,是指两个设备处于联机状态,只不过都在后台运行。

假脱机的原理,通俗的说,是在两个设备之间进行数据交换,一个设备传输数据的速度快,一个设备传输数据的速度慢。为了充分利用高速设备,在需要交换数据时,低速设备将数据输入到缓冲区,同时,高速设备无需等待低速设备,而是径直去处理其他Task,等低速设备将全部数据输入到缓存之后,高速设备再去缓冲区读取数据,然后快速处理,这样高速设备就不会闲置,提高设备的利用率。Spool 为了协调两个设备,需要用到一个缓冲区,低速设备向缓冲区中写数据,高速设备从缓冲区中读取数据。所以,假脱机技术的原理,是低速设备在后台利用缓冲区转存数据,高速设备从缓冲区获取数据,执行数据处理。

在 SQL Server的执行计划中,Spool 是逻辑运算符,分为Eager Spool 和 Lazy Spool:

  • Eager Spool 逻辑运算符:一次性将所有数据输入到临时的Spool中
  • Lazy Spool 逻辑运算符:逐批将数据输入到临时的Spool中

如果执行计划出现这两个操作符,表明 SQL Server 需要将中间结果集保存到临时存储区,在SQL Server中,临时存储区是指Worktable 或 Workfile, 用于存储临时结果集:

  • WorkFile: 用于存储Hash Join 和 Hash 聚合的临时结果集,小的临时结果集存储在Memory中;
  • WorkTable: 用于存储 Query Spool(table spool, index spool, and so on),Lob 变量,XML变量和游标的临时结果集;
  • Spill to tempdb:WorkFile和WorkTable都创建在内存中,如果临时结果集太大,分配的Memory容纳不了,那么,临时结果集会被保存到tempdb file中,即:spill to disk(tempdb files);
  • 查询性能降低:一般来说,SQL Server在执行计划中使用WorkFile 或 WorkTable,表明查询语句的性能较低

引用MSDN:

"Work files could be used to store temporary results for hash joins and hash aggregates. The returned value should be less than 20. Tempdb work files are used in processing hash operations when the amount of data being processed is too large to fit into the available memory." Possible problems: High values can indicate thrash in the tempdb file as well as poorly coded queries.

"Work tables could be used to store temporary results for query spool, lob variables, XML variables, and cursors. The returned value should be less than 20. Worktables are used for queries that use various spools (table spool, index spool, and so on)." Possible problems: High values could cause general slowdown.

二,查看Workfile 和 Worktable

查询优化器创建Workfile 和 Worktable 的目的是为了存储临时结果集,在执行查询时,设置 “Set Statistics IO On” ,能够看到查询语句创建的 Workfile 和 Worktable,以及临时存储区的IO信息,如图:

SQL Server 存储中间结果集

一般情况下,如果临时存储对象(Workfile 和 Worktable)被创建,说明查询的中间结果集太大,服务器的内存资源将被耗尽,导致SQL Server 必须使用Disk存储中间结果集,才能使查询操作继续执行,但是,可用的内存耗尽和额外的IO开销,都会降低SQL Server的的查询性能。

SQL Server在内存中创建Workfile 和 Worktable,在中间结果集较小时,中间结果集保存在内存中;如果结果集过大,保存在内存将增加内存压力,SQL Server将中间结果集转存到tempdb的数据文件中,即,从内存写入到Disk。在需要中间结果集时,从Disk File读取到内存中,产生额外的Disk IO,降低SQL Server的查询性能。

1,使用Worktable

关系引擎在执行 order by、group by或者union操作时,需要创建WorkTable,用于保存中间结果集。例如,在执行Order by 操作时,如果没有在排序字段上创建index,那么SQL Server查询优化器会在tempdb中创建一个WorkTable来缓存中间查询结果集,并对中间结果集进行排序。在系统需要时,自动创建创建在tempdb中创建WorkTable;当系统不再需要该WorkTable时,会自动从tempdb中删除。

优化方法:为了减少WorkTable的使用,应该优化SQL语句,减少不必要的group by,order by或Union操作,在select 子句中剔去不必要的column,使返回的结果集尽可能的小。

引用MSDN:

The relational engine may need to build a worktable to perform a logical operation specified in an SQL statement. Worktables are internal tables that are used to hold intermediate results. Worktables are generated for certain GROUP BY, ORDER BY, or UNION queries. For example, if an ORDER BY clause references columns that are not covered by any indexes, the relational engine may need to generate a worktable to sort the result set into the order requested. Worktables are also sometimes used as spools that temporarily hold the result of executing a part of a query plan. Worktables are built in tempdb and are dropped automatically when they are no longer needed.

2,使用WorkFile

在SQL Server执行Hash Join 或 Hash聚合操作,使用WorkFiles来存储临时结果集。

Hash Join 能够有效处理大量,未排序,未索引的输入;Hash Join在处理复杂查询返回的中间结果集时非常有用,是因为:

  • Intermediate results are not indexed (unless explicitly saved to disk and then indexed) and often are not suitably sorted for the next operation in the query plan.

  • Query optimizers estimate only intermediate result sizes. Because estimates can be very inaccurate for complex queries, algorithms to process intermediate results not only must be efficient, but also must degrade gracefully if an intermediate result turns out to be much larger than anticipated.

优化方法:为了减少WorkFile的使用,在和大表进行Join查询时,尽可能地使用Index Column,避免对无序数据进行Hash Join或Hash 聚合操作。

参考文档:

Operator of the Week – Spools, Eager Spool

Understanding Hash Joins

Tempdb usage: Workfiles

优化临时表使用,SQL语句性能提升100倍

SET STATISTICS IO- worktable/workfile

Beware misleading data from SET STATISTICS IO

Simple Query tuning with STATISTICS IO and Execution plans

Advanced Query Tuning Concepts

SQL Server, Access Methods Object

workfiles created/sec spiking out of control

SQLSERVER中的假脱机