I'm new to SQL and in my research of best performance I'm seeing everywhere to SET NOCOUNT ON in all of my queries to improve performance... I understand that it returns the rows affected and that's "most of the time" unnecessary data transmission, but my question is when would you want that? If ever? Why is it set to OFF as default? Can I set it to ON by default?
Let me explain why I use SET NOCOUNT ON and SET NOCOUNT OFF a lot.
I usually interact with the database by loading script files. I set SQL Server Management Studio to display the output as text.
Why do I do this, and why do I use SET NOCOUNT ?
I set the output as text as then I can see very easily what the queries have returned.
I might be sending 20 or 30 queries to the database, and if I return the results as grid makes it really hard to know what has happened, as there are so many tabs to look through.
And why use SET NOCOUNT ?
Well, the main reason is that I've probably deleted some rows, and if I use SET NOCOUNT OFF I can very quickly see whether I've deleted 10,246 rows, when I was only expecting to have deleted 7.
So basically, loading and running commands from a script file, setting the output to text, and setting SET NOCOUNT OFF tells me very quickly whether my commands have done as I expected.
I agree that, if you're not running commands from a text file, and setting output to text, the setting does seem pointless.
For the use case though that I describe, it really is useful.
Related
How do you get SQL Execution Plan in VS code? Something like this:
Sorry to say, but you do not.
Getting the raw data is not that complicated..
SET SHOWPLAN_TEXT ON
SET SHOWPLAN_ALL ON
SET SHOWPLAN_XML ON
SET STATISTICS PROFILE ON
SET STATISTICS XML ON -- The is the recommended option to use
But that deos NOT give you the visualization, and that is simply not built into VS Code. An extension WOULD possibly do it - but noone has to my knowledge written that one.
Sorry, sometimes the answer is just "not happening".
I know what XACT_ABORT is. There is a lot of info on why to set this to on. My question is why would someone set it to off? The point of a transaction is either everything is done or nothing is done. So why would someone set this to off? Why MS even choose off as the default is strange (The default for triggers is on and I know that).
After some digging I can only think of one decent reason as to why you would. That would be that you would want the transaction to continue processing regardless of any errors that are flagged. It might be that you want to deal with the errors later on rather than having the entire transaction rolled back.
There are also certain times when having XACT_ABORT isn't required for data modification statements but requirement is different to preference.
Source: MSDN
I'm building my own clone of http://statoverflow.com/sandbox (using the free controls provided to 10K users from Telerik). I have a proof of concept available I can use locally, but before I open it up to others I need to lock it down some more. Currently I run everything through a stored procedure that looks something like this:
CREATE PROCEDURE WebQuery
#QueryText nvarchar(1000)
AS
BEGIN
-- no writes, so no need to lock on select
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
-- throttles
SET ROWCOUNT 500
SET QUERY_GOVERNOR_COST_LIMIT 500
exec (#QueryText)
END
I need to do two things yet:
Replace QUERY_GOVERNOR_COST_LIMIT with an actual rather than estimated timeout, so no query runs longer than say 2 minutes.
Right now nothing stops users from just putting their own 'SET ROWCOUNT 50000;' in front of their query text to override my restriction, so I need to somehow limit the queries to a single statement or (preferrably) disallow the SET commands inside the exec function.
Any ideas?
You really plan to allow users to run arbitrary Ad-Hoc SQL? Only then can a user place in a SET to override your restrictions. If that's the case, you're best bet is to do some basic parsing using lexx/yacc or flex/bison (or your favorite CLR language tree parser) and detect invalid SET statements. Are you going to allow SET #variable=value though, which syntactically is a SET...
If you impersonate low privileged users via EXECUTE AS make sure you create an irreversible impersonation context, so the user does not simply execute REVERT and regain all the privileges :) You also must really understand the implications of database impersonation, make sure you read Extending Database Impersonation by Using EXECUTE AS.
Another thing to consider is deffering execution of requests to a queue. Since queue readers can be calibrated via MAX_QUEUE_READERS, you get a very cheap throttling. See Asynchronous procedure execution for a related article how to use queues to execute batches. This mechanism is different from resource governance, but I've seen it used to more effect that the governor itself.
Throwing this out there:
The EXEC statement appears to support impersonation. See http://msdn.microsoft.com/en-us/library/ms188332.aspx. Perhaps you can impersonate a limited user. I am looking into the availability of limitations that may prevent SET statements and the like.
On a very basic level, how about blocking any statement that doesn't start with SELECT? Or will other query starts be supported, like CTE's or DECLARE statements? 1000 chars isn't too much room to play with, but i'm not too clear what this is in the first place.
UPDATED
Ok, how about prefixing whatever they submit with SELECT TOP 500 FROM (
and appending a ). If they try to do multiple statements it'll throw an error you can catch. And to prevent denial of service, replace their starting SELECT with another SELECT TOP 500.
Doesn't help if they've appended an ORDER BY to something returning a million rows, though.
I am still learning sql server somewhat and recently came across a select query in a stored procedure which was causing a very slow fill of a dataset in c#. At first I thought this was to do with .NET but then found a suggestion to put in the stored procedure:
set implicit_transactions off
this seems to cure it but I would like to know why also I have seen other options such as:
set nocount off
set arithabort on
set concat_null_yields_null on
set ansi_nulls on
set cursor_close_on_commit off
set ansi_null_dflt_on on
set ansi_padding on
set ansi_warnings on
set quoted_identifier on
Does anyone know where to find good info on what each of these does and what is safe to use when I have stored procedures setup just to query of data for viewing.
I should note just to stop the usual use/don't use stored procedures debate these queries are complex select statements used on multiple programs in multiple languages it is the best place for them.
Edit: Got my answer didn't end up fully reviewing all the options but did find
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
Sped up the complex queries dramatically, I am not worried about the dirty read in this instance.
This is the page out of SQL Server Books Online (BOL) that you want. It explains all the SET statements that can be used in a session.
http://msdn.microsoft.com/en-us/library/ms190356.aspx
Ouch, someone, somewhere is playing with fire big-time.
I have never had a production scenario where I had to enable implicit transactions. I always open transactions when I need them and commit them when I am done. The problem with implicit transactions is its really easy to "leak" an open transaction which can lead to horrible issues. What this setting means is "please open a transaction for me the first time I run a statement if there is no transaction open, don't worry about committing it".
For example have a look at the following examples:
set implicit_transactions on
go
select top 10 * from sysobjects
And
set implicit_transactions off
go
begin tran
select top 10 * from sysobjects
They both do the exact same thing, however in the second statement its pretty clear someone forgot to commit the transaction. This can get very complicated to track down if you have this set in an obscure place.
The best place to get documentation for all the set statements is the old trusty sql server books online. It together with a bit of experimentation in query analyzer are usually all that is required to get a grasp of most settings.
I would strongly recommend you find out who is setting up implicit transactions, find out why they are doing it, and remove the setting if its not really required. Also, you must confirm that whoever uses this setting commits their implicitly open transactions.
What was probably going on is that you had an open transaction that was blocking a bit of your your stored proc, and somewhere you have a timeout that is occurring, raising an error and being handled in code, when that timeout happens your stored proc continues running. My guess is that the delay is usually 30 seconds exactly.
I think you need to look deeper into your stored procedure. I don't think that SET IMPLICIT_TRANSACTIONS is really going to be what's sped up your procedure, I think it's probably a coincidence.
One thing that may be worth a look at is what is passed from the client to the server by using the profiler.
We had an odd situation where the default SET arguments for the ADO connection were causing an SP to take ages to run from the client which we resolved by looking at exactly what the server was receiving from the client, complete with default SET arguments compared to what was sent when executing from SSMS. We then made the client pass the same SET statements as those sent by SSMS.
This may be way off track but it is a useful method to use when the SP executes in a timely fashion on the server but not from the client.
What are the advantages and disadvantages of turning NOCOUNT off in SQL server queries?
From SQL BOL:
SET NOCOUNT ON prevents the sending of
DONE_IN_PROC messages to the client
for each statement in a stored
procedure. For stored procedures that
contain several statements that do not
return much actual data, setting SET
NOCOUNT to ON can provide a
significant performance boost, because
network traffic is greatly reduced.
See http://msdn.microsoft.com/en-us/library/ms189837.aspx for more details.
Also, this article on SQLServerCentral is great on this subject:
Performance Effects of NOCOUNT
And it's not just the network traffic that is reduced. There is a boost internal to SQL Server because the execution plan can be optimized due to reduction of an extra query to figure out how many rows were affected.
It simply stops the message that shows the # of rows effected for being sent/displayed, which provides a performance benefit, especially if you have many statements that will return the message. It improves performance since less data is being sent over the network (between the sql server and front end).
More at BOL: SET NOCOUNT
I always have it set to ON for the reasons above, but if you have more than 1 result set in your proc it could mess up client code
I personally like to turn NOCOUNT on for queries that get run in an manual fashion and use a lot of Print statements to output debugging messages. In this way, your output would look less like:
Updating usernames
(287 rows updated)
Done
Updating passwords
(287 rows updated)
Done
Doing the next thing
(1127 rows updated)
Done
And more like
Updating usernames
Done
Updating passwords
Done
Doing the next thing
Done
Depending on the sensitivity of what you're updating, sometimes it is helpful to include the counts; however, for complex scripts with a lot of output I usually like to leave them out.
SET NOCOUNT ON is an oneline Statement, Sql server sends message back to client.this is performed for Every Process(ie .. select,insert,update,delete).if you avoid this message we can improve overall performance for our Database and also reduce network traffic
For EX:
declare #a table(id int)
set nocount on
insert #a select 1 union select 2
set nocount off
Stops the message indicating the number of rows affected by a Transact-SQL statement from being returned as part of the results.