关于tsql:避免在SQL Server上进行急切假脱机操作的方法

关于tsql:避免在SQL Server上进行急切假脱机操作的方法

Ways to avoid eager spool operations on SQL Server

我有一个涉及到存储过程的ETL过程,该过程大量使用SELECT INTO语句(最小记录,因此速度更快,因为它们生成的日志流量较少)。在一个特定的存储过程中发生的这批工作中,一些最昂贵的操作是急切的假脱机,它们似乎只是缓冲查询结果,然后将其复制到刚制成的表中。

急切的线轴的MSDN文档很少。有没有人对这些是否真的必要(以及在什么情况下)有更深入的了解?我有一些理论可能有意义,也可能没有意义,但无法成功地从查询中消除这些理论。

.sqlplan文件很大(160kb),所以我想直接将它们发布到论坛上可能并不合理。

因此,以下是一些可能适合特定答案的理论:

  • 该查询使用一些UDF进行数据转换,例如解析格式化的日期。这种数据转换是否需要在构造表之前使用急切的线轴为表分配明智的类型(例如varchar长度)?
  • 作为上述问题的扩展,是否有人对查询中驱动此操作的原因有更深入的了解?

我对假脱机的理解是,这对您的执行计划有些不利。是的,它占了您大量的查询成本,但是实际上,这是SQL Server自动进行的一项优化,从而可以避免进行昂贵的重新扫描。如果要避免假脱机,那么位于其上的执行树的成本将会上升,几乎可以肯定,整个查询的成本都会增加。我对什么可能导致数据库的查询优化器以这种方式解析执行没有什么特别的了解,尤其是在没有看到SQL代码的情况下,但是您最好还是信任它的行为。

但是,这并不意味着无法优化执行计划,具体取决于您要做什么以及源数据的易变性。在执行SELECT INTO时,通常会在执行计划中看到假脱机项目,并且这可能与读取隔离有关。如果适合您的特定情况,则可以尝试将事务隔离级别降低到成本更低的程度,和/或使用NOLOCK提示。我发现在复杂的,对性能至关重要的查询中,NOLOCK如果安全且适用于您的数据,即使似乎没有任何理由,它也可以极大地提高查询的执行速度。

在这种情况下,如果尝试使用READ UNCOMMITTEDNOLOCK提示,则可以消除某些假脱机。 (显然,如果这可能会使您处于不一致状态,但是每个人的数据隔离要求都不同,那么您就不想这样做。) TOP运算符和OR运算符有时可能会导致假脱机,但是我怀疑您是否正在ETL流程中进行任何此类操作...

您说对了,您的UDF也可能是罪魁祸首。如果您只使用一次每个UDF,尝试将它们内联以查看您是否获得了较大的性能优势,这将是一个有趣的实验。 (而且,如果您无法找到一种将它们与查询内联地编写的方法,则可能就是它们可能导致假脱机的原因)。

我要看的最后一件事是,如果您要进行任何可以重新排序的联接,请尝试使用提示来强制联接顺序以您所知道的最有选择性的顺序发生。这是可以达到的,但是如果您已经坚持进行优化,那么尝试它也没有什么坏处。


推荐阅读