set nocount on能减少网络传输开销,因为它抑制每条dml/select执行后发送的“(5行受影响)”类done_in_proc状态消息,这些消息在tds协议层以独立小帧发送,高并发下积少成多拖慢响应。

为什么SET NOCOUNT ON能减少网络传输开销
它不减少数据本身,而是砍掉每条 SELECT、INSERT、UPDATE、DELETE 执行后发给客户端的 (5 rows affected) 这类 DONE_IN_PROC 状态消息。这些消息在 TDS 协议层被打包成独立小帧发送——一个含 20 次 UPDATE 的循环,就多发 20 次无业务价值的小包。高并发下积少成多,拖慢整体响应。
在存储过程中怎么加才有效
必须放在 BEGIN 后第一行,且无需配对写 SET NOCOUNT OFF:
-
SET NOCOUNT ON作用域仅限当前批处理(即该存储过程执行上下文),退出即自动失效 - 强行加
SET NOCOUNT OFF可能污染调用方的会话设置,尤其当调用链嵌套时 - 触发器里也建议加,因为触发器隐式运行在用户语句上下文中,不加容易让外层应用收到意料之外的
DONE_IN_PROC
不加SET NOCOUNT ON会触发哪些客户端异常
不是报错,而是让客户端“误判结果集结构”,典型现象包括:
- ADO.NET 中
SqlCommand.ExecuteNonQuery()抛InvalidOperationException: There is already an open data reader associated with this command—— 多出来的行计数被当成未读完的结果集 - Entity Framework 映射失败或报
Invalid operation. The connection is closed.—— 框架试图消费所有结果集,却被冗余消息打断 - Power BI 刷新时报
无法识别多个结果集,尤其当存储过程含循环或多个 DML 语句时
它会影响 @@ROWCOUNT 或业务逻辑吗
完全不影响。无论 SET NOCOUNT ON 还是 OFF,@@ROWCOUNT 都准确更新,所有 IF @@ROWCOUNT = 0 RAISERROR 类判断照常工作。真正被屏蔽的只是发给客户端的那条文本消息,不是行数统计本身。
最容易被忽略的是:这个优化不省 CPU、不省磁盘,只省网络帧;而很多性能瓶颈恰恰卡在 TDS 层吞吐上,不是 SQL 引擎里。











