问题 TOP与SET ROWCOUNT


性能之间是否存在差异? TOP 和 SET ROWCOUNT 或者他们只是以同样的方式执行?


4551
2018-01-22 11:32


起源



答案:


是的,功能上他们是一回事。据我所知,两者之间没有明显的性能差异。

有一点需要注意的是,一旦你有了 set rowcount 这将在连接的生命周期中持续存在,因此请确保将其重置为 0 一旦你完成它。


编辑(发表马丁的评论)

SET ROWCOUNT的范围仅适用于当前过程。这包括当前程序调用的过程。它还包括通过EXEC或SP_EXECUTESQL执行的动态SQL,它们被视为“子”范围。

请注意,SET ROWCOUNT位于BEGIN / END范围内,但它超出了范围。

create proc test1
as
begin
    begin
    set rowcount 100
    end
    exec ('select top 101 * from master..spt_values')
end
GO

exec test1
select top 102 * from master..spt_values

结果= 100行,然后102行


9
2018-01-22 11:36



stackoverflow.com/questions/863714/sql-rowcount-vs-top  - 这两者之间列出的其他差异很少,任何人都有兴趣。 - VoodooChild
我不认为最后一行是正确的。在这里看到我的答案 stackoverflow.com/questions/5383761/... - Martin Smith
@Richard:我一直都这么认为 BEGIN...END 只是一个复合陈述。从未认为它也是定义范围。也许'全球' BEGIN...END 是一种特殊情况,它用于明确指定编程对象主体的开头和结尾。但即便如此,我想说,它只是将范围可视化 一个编程对象,没有定义自己的。 - Andriy M
无论何时执行动态SQL,都会创建一个在其自身连接上运行的新批处理。这不是一个好例子,即使包装在Begin和End中,Set RowCount也能正常工作。 - MikeTeeVee


答案:


是的,功能上他们是一回事。据我所知,两者之间没有明显的性能差异。

有一点需要注意的是,一旦你有了 set rowcount 这将在连接的生命周期中持续存在,因此请确保将其重置为 0 一旦你完成它。


编辑(发表马丁的评论)

SET ROWCOUNT的范围仅适用于当前过程。这包括当前程序调用的过程。它还包括通过EXEC或SP_EXECUTESQL执行的动态SQL,它们被视为“子”范围。

请注意,SET ROWCOUNT位于BEGIN / END范围内,但它超出了范围。

create proc test1
as
begin
    begin
    set rowcount 100
    end
    exec ('select top 101 * from master..spt_values')
end
GO

exec test1
select top 102 * from master..spt_values

结果= 100行,然后102行


9
2018-01-22 11:36



stackoverflow.com/questions/863714/sql-rowcount-vs-top  - 这两者之间列出的其他差异很少,任何人都有兴趣。 - VoodooChild
我不认为最后一行是正确的。在这里看到我的答案 stackoverflow.com/questions/5383761/... - Martin Smith
@Richard:我一直都这么认为 BEGIN...END 只是一个复合陈述。从未认为它也是定义范围。也许'全球' BEGIN...END 是一种特殊情况,它用于明确指定编程对象主体的开头和结尾。但即便如此,我想说,它只是将范围可视化 一个编程对象,没有定义自己的。 - Andriy M
无论何时执行动态SQL,都会创建一个在其自身连接上运行的新批处理。这不是一个好例子,即使包装在Begin和End中,Set RowCount也能正常工作。 - MikeTeeVee


据BOL称,还有一个关于性能的说明:

作为SELECT语句的一部分,查询优化器可以在查询优化期间考虑TOP或FETCH子句中的表达式的值。由于SET ROWCOUNT在执行查询的语句之外使用,因此无法在查询计划中考虑其值。

关于BOL的文章

这意味着实际上可能存在性能差异。


4
2018-03-20 14:54