Inspired by this question where there are differing views on SET NOCOUNT...
Should we use SET NOCOUNT ON for SQL Server? If not, why not?
It took me a lot of digging to find real benchmark figures around NOCOUNT, so I figured I'd share a quick summary.
At the risk of making things more complicated, I encourage a slightly different rule to all those I see above:
NOCOUNT ON
at the top of a proc, before you do any work in the proc, but also always SET NOCOUNT OFF
again, before returning any recordsets from the stored proc. So "generally keep nocount on, except when you are actually returning a resultset". I don't know any ways that this can break any client code, it means client code never needs to know anything about the proc internals, and it isn't particularly onerous.
Ok now I've done my research, here is the deal:
In TDS protocol, SET NOCOUNT ON
only saves 9-bytes per query while the text "SET NOCOUNT ON" itself is a whopping 14 bytes. I used to think that 123 row(s) affected
was returned from server in plain text in a separate network packet but that's not the case. It's in fact a small structure called DONE_IN_PROC
embedded in the response. It's not a separate network packet so no roundtrips are wasted.
I think you can stick to default counting behavior almost always without worrying about the performance. There are some cases though, where calculating the number of rows beforehand would impact the performance, such as a forward-only cursor. In that case NOCOUNT might be a necessity. Other than that, there is absolutely no need to follow "use NOCOUNT wherever possible" motto.
Here is a very detailed analysis about insignificance of SET NOCOUNT
setting: http://daleburnett.com/2014/01/everything-ever-wanted-know-set-nocount/
I guess to some degree it's a DBA vs. developer issue.
As a dev mostly, I'd say don't use it unless you absolutely positively have to - because using it can break your ADO.NET code (as documented by Microsoft).
And I guess as a DBA, you'd be more on the other side - use it whenever possible unless you really must prevent it's usage.
Also, if your devs ever use the "RecordsAffected" being returned by ADO.NET's ExecuteNonQuery
method call, you're in trouble if everyone uses SET NOCOUNT ON
since in this case, ExecuteNonQuery will always return 0.
Also see Peter Bromberg's blog post and check out his position.
So it really boils down to who gets to set the standards :-)
Marc
Sometimes even the simplest things can make a difference. One of these simple items that should be part of every stored procedure is SET NOCOUNT ON
. This one line of code, put at the top of a stored procedure turns off the messages that SQL Server sends back to the client after each T-SQL statement is executed. This is performed for all SELECT
, INSERT
, UPDATE
, and DELETE
statements. Having this information is handy when you run a T-SQL statement in a query window, but when stored procedures are run there is no need for this information to be passed back to the client.
By removing this extra overhead from the network it can greatly improve overall performance for your database and application.
If you still need to get the number of rows affected by the T-SQL statement that is executing you can still use the @@ROWCOUNT
option. By issuing a SET NOCOUNT ON
this function (@@ROWCOUNT
) still works and can still be used in your stored procedures to identify how many rows were affected by the statement.