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

时间:2008-09-17 08:58:18

标签: sql-server tsql spool eager

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

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

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

所以,这里有一些可能适合特定答案的理论:

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

1 个答案:

答案 0 :(得分:30)

我对假脱机的理解是,它对你的执行计划来说是一个红色的鲱鱼。是的,它占了很多查询成本,但它实际上是SQL Server自动进行的优化,因此可以避免代价高昂的重新扫描。如果你要避免假脱机,它所依赖的执行树的成本会上升,几乎可以肯定整个查询的成本会增加。我没有特别深入了解特别是可能导致数据库的查询优化器以这种方式解析执行的问题,特别是在没有看到SQL代码的情况下,但您可能最好不要相信它的行为。

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

在这种情况下,如果您尝试READ UNCOMMITTEDNOLOCK提示,您可以删除一些假脱机。 (显然你不想这样做,如果它可能让你处于一个不一致的状态,但每个人的数据隔离要求都不同)。 TOP运算符和OR运算符偶尔会导致假脱机,但我怀疑您在ETL过程中正在执行任何操作...

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

我要看的最后一件事是,如果您正在进行任何可以重新排序的连接,请尝试使用提示强制连接顺序在您知道的最具选择性的顺序中发生。这有点可以实现,但如果您已经进行了优化,那么尝试它并没有什么坏处。