SET NOCOUNT ON 仅抑制 DONE_IN_PROC 消息,不阻止结果集返回或影响 @@ROWCOUNT;它减少网络帧开销与客户端解析错误,须置于 BEGIN 后首行且无需配对 OFF。

SET NOCOUNT ON 抑制的是 DONE_IN_PROC 消息,不是结果集
它不阻止 SELECT 返回数据,也不影响 @@ROWCOUNT;它只屏蔽每条 INSERT、UPDATE、DELETE、SELECT 执行后由 SQL Server 自动发出的 (5 行受影响) 类文本消息。这类消息在 SSMS 的“消息”选项卡可见,但本质是 TDS 协议层的独立状态包(DONE_IN_PROC),每个都占一个网络帧。
高并发下小消息积少成多
一个含 20 次 UPDATE 的循环存储过程,在 SET NOCOUNT OFF 下会额外发送 20 个 DONE_IN_PROC 包——每个约 100–200 字节,看似微小,但在 OLTP 场景中:
- 每秒数百次调用 → 每秒多发数万个包
- 网络栈频繁中断、缓冲区竞争加剧
- ADO.NET 等客户端需逐个解析并丢弃,徒增 CPU 开销
实测显示:插入 1 万行的存储过程,开启 SET NOCOUNT ON 可减少约 20KB 冗余流量
客户端误解析导致异常比性能下降更常见
多数问题不是慢,而是“错”:
- SqlCommand.ExecuteNonQuery() 抛 InvalidOperationException: There is already an open data reader —— 因为行计数消息被当成未读完的结果集
- Entity Framework 映射失败,报 Invalid operation. The connection is closed.
- SSIS 数据流任务中断,Power BI 刷新报 无法识别多个结果集
这些都不是业务逻辑错误,而是客户端框架试图消费所有返回内容时,被冗余的 DONE_IN_PROC 消息干扰了结果集边界判断
必须放在 BEGIN 后第一行,且无需配对 OFF
SET NOCOUNT ON 的作用域仅限当前批处理(即存储过程内部),退出即自动失效:
- ✅ 正确写法:BEGIN SET NOCOUNT ON; ...
- ❌ 不要写 SET NOCOUNT OFF 收尾——可能污染调用方上下文
- ❌ 不要依赖模板默认值——SQL Server 默认是 OFF,不显式设就等于裸奔
真正容易被忽略的是:它不省 CPU、不省磁盘,只省网络帧;而现代应用的瓶颈,往往卡在协议层那几十字节的“废话”上











