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

时间:2020-03-05 18:58:20  来源:igfitidea点击:

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

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

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

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

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

解决方案

回答

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

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

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

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

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