SET NOCOUNT ON用法

受到SET NOCOUNT有不同观点的这个问题的启发…

我们应该使用SQL Server的SET NOCOUNT ON吗? 如果没有,为什么不呢?

它的作用编辑6,2011年7月22日

它抑制任何DML之后的“xx rows affected”消息。 这是一个结果集,当发送时,客户端必须处理它。 它很小,但是可以测量(见下面的答案)

对于触发器等,客户端将收到多个“受影响的xx行”,这会导致一些ORM,MS Access,JPA等所有错误的方式(见下面的编辑)

背景:

一般接受的最佳实践(我认为,直到这个问题)是在SQL Server中的触发器和存储过程中使用SET NOCOUNT ON 。 我们在任何地方都使用它,并且快速的谷歌显示了许多SQL Server MVP也同意。

MSDN说这可以打破.net SQLDataAdapter 。

现在,这意味着SQLDataAdapter仅限于完全简单的CRUD处理,因为它期望“n行受影响”消息匹配。 所以,我不能使用:

  • 如果存在,以避免重复(不受行影响的消息) 注意:谨慎使用
  • 不存在(更less行然后预期
  • 过滤出微不足道的更新(例如,实际上没有数据发生变化)
  • 做任何表访问之前(如日志logging)
  • 隐藏复杂性或denormlisation
  • 等等

在marc_s(谁知道他的SQL的东西)的问题说,不要使用它。 这与我认为的不同(我也认为我自己在SQL方面也有点胜任)。

有可能我错过了一些东西(随便指出一些明显的东西),但是你们有什么想法呢?

注意:我看到这个错误已经有好几年了,因为我现在不使用SQLDataAdapter。

评论和问题后编辑:

编辑:更多的想法…

我们有多个客户端:一个可以使用C#SQLDataAdaptor,另一个可以使用Java的nHibernate。 SET NOCOUNT ON可能会以不同的方式影响这些SET NOCOUNT ON

如果你把存储过程看作是方法,那么为了你自己的目的,假定某些内部处理以某种方式工作,这是坏forms(反模式)。

编辑2: 触发打破nHibernate问题 ,其中SET NOCOUNT ON不能设置

(不,这不是重复的)

编辑3:还有更多信息,感谢我的MVP同事

  • KB 240882 ,在SQL 2000和更早的版本上导致断开的问题
  • 性能增益演示

编辑2011年5月13日

打破Linq 2 SQL时,也没有指定?

编辑5:14六月2011

打破JPA,与表variables存储过程: JPA 2.0是否支持SQL Server表variables?

编辑6:15八月2011

SSMS“编辑行”数据网格需要SET NOCOUNT ON: 使用GROUP BY更新触发器

编辑7:07三月2013

@RemusRusanu更深入的细节:
SET NOCOUNT ON是否真的使性能有所改观

好吧,我已经完成了我的研究,这是交易:

  • 在TDS协议中, SET NOCOUNT ON只保存每个查询9个字节 ,这似乎并不多。 我以前认为9 row(s) affected是以纯文本forms从服务器返回的,但似乎并不是这样。 这实际上是一个名为DONE_IN_PROC的小消息包。

  • 根据“ 改进.NET应用程序的性能和可伸缩性 ”(第541页)一书,Microsoft实际上鼓励在存储过程中使用SET NOCOUNT ON 。 我不会将我的devise决定基于SqlDataAdapter。

所以我认为如果成本低于切换到其他技术,你可以坚持SET NOCOUNT ON的。 我仍然会考虑放弃SqlDataAdapter,因为你还不知道接下来会遇到什么样的devise怪癖。

编辑:@racingsnail指出,networking往返延迟是一个比数据包大小更大的性能杀手。 他有一个点,但是第二个networking数据包不会像往返延迟那样产生相同的延迟,因为这些数据包是串联发送的,不需要确认。 所以它可能会导致比实际的networking往返延迟less得多的延迟。

编辑2:这是一个非常详细的分析关于SET NOCOUNT设置的微不足道的开销: http : //daleburnett.com/2014/01/everything-ever-wanted-know-set-nocount/

我花了很多时间在NOCOUNT上find真正的基准数据,所以我想我会分享一个快速总结。

  • 如果您的存储过程使用游标执行很多非常快速的操作而没有返回结果,那么拥有NOCOUNT OFF可能需要大约10倍的时间。 1这是最坏的情况。
  • 如果您的存储过程只执行一次快速操作而没有返回结果,那么设置NOCOUNT ON会使性能提高3%左右。 2这将与典型的插入或更新过程一致。
  • 如果你的存储过程返回结果(即你select了一些东西),性能差异会随着结果集的大小成比例地减小。
  • 当SET NOCOUNT为ON时,不会返回count(表示受Transact-SQL语句影响的行数)。 SET NOCOUNT为OFF时,返回计数。 它与任何SELECT,INSERT,UPDATE,DELETE语句一起使用。

  • SET NOCOUNT的设置是在执行或运行时设置的,而不是在parsing时间。

  • SET NOCOUNT ON改善存储过程(SP)性能。

  • 语法:SET NOCOUNT {ON | OFF}

SET NOCOUNT ON的示例:

在这里输入图像描述

SET NOCOUNT OFF的示例:

在这里输入图像描述

我想在某种程度上这是一个DBA与开发人员的问题。

作为一个开发大多数人,我会说不要使用它,除非你绝对肯定 – 因为使用它可以打破你的ADO.NET代码(由微软logging)。

我想作为一名DBA,你会更多的在另一边 – 尽可能地使用它,除非你真的必须防止它的使用。

另外,如果您的开发者使用ADO.NET的ExecuteNonQuery方法调用返回的“RecordsAffected”,那么如果每个人都使用SET NOCOUNT ON ,则会遇到麻烦,因为在这种情况下,ExecuteNonQuery将始终返回0。

另请参阅Peter Bromberg的博客文章 ,看看他的位置。

所以这真的归结为谁来设置标准:-)

渣子

如果你说你也可能有不同的客户端,如果SET NOCOUNT没有设置为ON,传统的ADO会出现问题。

我经常遇到一个问题:如果一个存储过程执行了多个语句(因此返回一些“xxx rows affected”消息),ADO似乎不处理这个问题,并引发错误“无法更改Recordset对象的ActiveConnection属性其中有一个Command对象作为其源。“

所以我一般主张把它设置为ON,除非真的有很好的理由不这样做。 你可能已经find了真的很好的理由,我需要去读更多。

冒着让事情变得更复杂的风险,我鼓励我在上面看到的所有人都有一个不同的规则:

  • 在proc中执行任何操作之前,始终在proc的顶部设置NOCOUNT ON ,但在从存储过程返回任何logging集之前,总是要再次SET NOCOUNT OFF

所以“除了当你实际返回一个结果集之外,一般不会打开nocount”。 我不知道有什么方法可以破坏任何客户端代码,这意味着客户端代码永远不需要知道任何关于proc内部的东西,并且不是特别繁重。

关于打破NHibernate的触发器,我亲身体验过。 基本上,当NH进行UPDATE时,它期望受到一定数量的行的影响。 通过将SET NOCOUNT ON添加到触发器,可以将行数返回到NH预期的值,从而解决问题。 所以是的,我肯定会build议closures触发器,如果​​你使用NH。

关于SP中的使用,这是个人喜好的问题。 我一直在排倒数,但是再一次,也没有任何真正有力的论据。

另一方面,你应该考虑转移到基于SP架构,那么你甚至不会有这个问题。

我不知道如何testing客户端和SQL之间的SET NOCOUNT ON,所以我testing了其他SET命令“SET TRANSACTION ISOLATION LEVEL READ UNCIMMITTED”

我从连接发送了一个命令,改变了SQL的默认行为(READ COMMITTED),并在下一个命令中进行了更改。 当我改变存储过程中的ISOLATION级别时,它并没有改变下一个命令的连接行为。

目前的结论,

  1. 更改存储过程中的设置不会更改连接的默认设置。
  2. 通过使用ADOCOnnection发送命令来更改设置会更改默认行为。

我认为这与其他SET命令如“SET NOCOUNT ON”

 SET NOCOUNT ON; 

这行代码在SQL中用于不返回查询执行中受影响的数字行。 如果我们不需要受影响的行数,我们可以使用它,因为这将有助于节省内存使用量并增加查询执行的速度。

如果(设置不计数==关)

{那么它会保存多lesslogging受影响的数据,所以降低性能} else {它不会跟踪logging的变化,从而改善perfomace}}

我知道这是一个很老的问题。 但只是为了更新。

使用“SET NOCOUNT ON”的最佳方法是将其作为第一个语句放在SP中,并在最后一个SELECT语句之前再次将其设置为OFF。

SET NOCOUNT ON; 以上代码将在DML / DDL命令执行后,将由SQL Server引擎生成的消息停止到前面的结果窗口。

为什么我们这样做? 由于SQL服务器引擎需要一些资源来获取状态并生成消息,因此它被认为是Sql服务器引擎的重载。所以我们设置了noncount消息。

在这里你可以看到,你可以使用这个工具来创build一个新的程序。 包括设置NOCOUNT ON,funciona correctamente。 Es curioso ver como en el Administrador Corporativo siempre funciona bien。