SQL Server 存储中间结果集
在执行查询语句时,有一些操作符会产生中间结果集,例如:Hash Join和Hash Aggregate操作产生的Hash Table,排序和分组操作会产生中间结果集等,后续的操作符对中间结果集执行操作,以响应用户的请求。
SQL Server的Spool(假脱机)操作符,用于把前一个操作符处理的数据(又称作中间结果集)存储到一个隐藏的临时结构中,以便在执行过程中重用这些数据。这个临时结构都创建在tempdb中,通常的结构是工作表(worktable)和工作文件(workfile)。假脱机运算符会取出表或索引结构中的一部分的数据集,将他们存放在tempdb数据库的临时结构里,我推测:如果这个临时结构用于存储表数据,称作worktable;如果这个临时结构存储的是Hash表,称作workfile。
一,Spool 操作符
在 SQL Server的执行计划中,Spool主要分为Eager Spool 和 Lazy Spool 这两个逻辑操作符:
- Eager Spool:一次性把所有数据存储到临时结构中,它是一个阻塞性的操作符,这意味着它需要读取输入中的所有数据,然后处理完所有的数据行之后,才向下一个操作符返回结果,也就是说,除非Eager Spool把所有的数据行都处理完成,否则无法访问到这些数据。
- Lazy Spool:逐行把数据存储到临时结构中,它是一个非阻塞性的操作符,这意味着它可以边读取数据,边向下一个操作符输出数据,也就是说,在Lazy Spool读取完所有的数据之前,可以访问这些数据。
如果执行计划中出现这两个操作符,表明 SQL Server 需要将中间结果集保存到临时存储区,在SQL Server中,临时存储区是指Worktable 或 Workfile,都创建在tempdb中, 用于临时存储中间结果集,以便后续的操作符重用数据:
- Workfile: 用于存储Hash Join 和 Hash 聚合产生的哈希表,小的临时结果集存储在Memory中;
- Worktable: 用于存储 Query Spool(table spool, index spool, and so on),Lob 变量,XML变量和游标的临时结果集;
WorkFile和WorkTable都创建在内存中,如果临时结果集太大,分配的Memory容纳不了,那么临时结果集就会被写入到tempdb的文件中,即:spill to disk(tempdb files),也就是说,调用IO子系统把数据写入到硬盘中,这会降低查询语句的执行性能。一般来说,如果SQL Server在执行计划中使用WorkFile 或 WorkTable,那么表明查询语句的性能较低
引用MSDN中对workfile 和 worktable的描述:
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用于存储临时数据,如果数据量超过20,那么workfile和worktable中的数据会被写入到tempdb的文件中去。
二,Workfile 和 Worktable的应用场景
查询优化器创建Workfile 和 Worktable 的目的是为了存储临时结果集,在执行查询时,设置 “Set Statistics IO On” ,能够看到查询语句创建的 Workfile 和 Worktable,以及临时存储区的IO信息,如图:
一般情况下,如果临时存储对象(Workfile 和 Worktable)被创建,说明查询的中间结果集太大,服务器的内存资源将被耗尽,导致SQL Server 必须使用Disk存储中间结果集,才能使查询操作继续执行,但是,可用的内存耗尽和额外的IO开销,都会降低查询语句的执行性能。
SQL Server查询优化器创建Workfile 和 Worktable存储中间结果集,当中间结果集较小时,中间结果集会被保存在内存中;如果结果集过大,为了减轻系统内存的压力,SQL Server会把中间结果集转存到tempdb的数据文件中,也就是说,把数据集从内存写入到Disk文件中。在重新使用中间结果集时,SQL Server从Disk File把数据读取到内存中,这回产生额外的Disk IO,降低SQL Server的查询性能。
1,使用Worktable
worktable是一个内部的关系表,用于存储中间结果集。关系引擎在执行 order by、group by或者union操作时,会创建Worktable,例如,在执行Order by 操作时,如果表没有在排序字段上创建索引,那么SQL Server查询优化器会在tempdb中创建一个Worktable来缓存执行计划产生的中间结果集,并对中间结果集进行排序。SQL Server在有需要时自动在tempdb中创建Worktable;当不再需要中间数据时,SQL Servere会自动从tempdb中删除worktable。
引用MSDN中关于使用worktable的描述:
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.
优化方法:为了减少Worktable的使用,应该优化TSQL语句,减少不必要的group by,order by或Union操作,在select 子句中剔去不必要的column,使返回的结果集尽可能的小。
2,使用Workfile
SQL Server在执行Hash Join 或 Hash聚合操作时,创建Workfiles来存储哈希表,哈希表是一个链式结构。
Hash Join 能够有效处理大量,未排序,未索引的输入;为了减少Workfile的使用,在和大表进行Join查询时,尽可能地使用索引列,进行Hash Join或Hash 聚合操作。
参考文档: