41

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

关于Eager spools的 MSDN 文档非常少。有没有人对这些是否真的有必要(以及在什么情况下)有更深入的了解?我有一些理论可能有意义,也可能没有意义,但没有成功从查询中消除这些理论。

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

因此,这里有一些可能适用于特定答案的理论:

  • 该查询使用一些 UDF 进行数据转换,例如解析格式化的日期。这种数据转换是否需要在构建表之前使用急切的假脱机来为表分配合理的类型(例如 varchar 长度)?
  • 作为上述问题的扩展,是否有人对查询中驱动此操作或不驱动此操作的内容有更深入的了解?
4

1 回答 1

34

我对假脱机的理解是,它对您的执行计划有点牵强。是的,它占了您查询成本的很大一部分,但它实际上是 SQL Server 自动进行的优化,因此它可以避免代价高昂的重新扫描。如果要避免假脱机,它所在的执行树的成本会上升,几乎可以肯定整个查询的成本会增加。对于可能导致数据库的查询优化器以这种方式解析执行的具体原因,我没有任何特别的见解,尤其是在没有看到 SQL 代码的情况下,但您最好相信它的行为。

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

在这种情况下,如果您尝试READ UNCOMMITTEDNOLOCK提示,您也许可以消除一些 Spools。(很明显,如果这样做可能会使您处于不一致的状态,那么您不希望这样做,但是每个人的数据隔离要求都不同)。TOP运算符和运算OR符偶尔会导致假脱机,但我怀疑您是否在 ETL 过程中执行任何这些...

您说得对,您的 UDF 也可能是罪魁祸首。如果您只使用每个 UDF 一次,那么尝试将它们内联以查看您是否获得了很大的性能优势,这将是一个有趣的实验。(如果你想不出一种方法将它们与查询内联,这可能就是它们可能导致假脱机的原因)。

One last thing I would look at is that, if you're doing any joins that can be re-ordered, try using a hint to force the join order to happen in what you know to be the most selective order. That's a bit of a reach but it doesn't hurt to try it if you're already stuck optimizing.

于 2008-09-17T20:23:10.133 回答