14

I'm trying to get query execution time, but I also want to hide the query output. I just want the elapsed time - no output.

Example

DECLARE @Start datetime
DECLARE @End datetime

SELECT @StartTimeWA=GETDATE() 

SELECT 
       [id] 
      ,[database_id]
      ,[proc_name]
      ,[exec_t] from
  [DB].[dbo].[STAT] 

SELECT @End=GETDATE()

SELECT DATEDIFF(MS,@Start,@End) AS [Duration]

At the moment, I get query output and at the bottom my duration, which is the only thing I want as far as the output goes. I haven't been able to do this and wondering whether anyone else has come across similar problems? This is something I want to do in T-SQL not Management Studio or anything like that.

I'm trying to monitor the time it takes to run the select statement and report back to a server. I have an external monitor server which will run that every minute and get the time back (duration it took) which I will use over time to trend / baseline. As the current query spits out the select results and my duration it skews it, and my monitor server gets confused. I just wanted the duration column. I will also be doing this for inserts, which will be straightforward as it won't need to perform a select.

I'm trying to do this purely in T-SQL. I don't want to use DMVs as I want to get the time it takes (snapshot) when I run a query and check whether this changes over time when the server goes through the various levels of load as this will give me a good idea as to whether query execution time changes.

0

3 Answers 3

31

There are a lot of different ways to do this.

I don't usually recommend inserting into a #temp table, since any tempdb load or autogrowth may impact the results, and I definitely don't recommend using a @table variable, since modifications to those are forced serial (no parallel plan can be used), which may change actual query times.

Variable Assignment

You can declare a variable and assign your columns to it, like this:

DECLARE @Start datetime
DECLARE @End datetime
DECLARE @blob_eater SQL_VARIANT;

SELECT @StartTimeWA=GETDATE() 

SELECT 
       @blob_eater = [id] 
      ,@blob_eater = [database_id]
      ,@blob_eater = [proc_name]
      ,@blob_eater = [exec_t] from
  [DB].[dbo].[STAT] 

SELECT @End=GETDATE()

SELECT DATEDIFF(MS,@Start,@End) AS [Duration]

Though doing this may prevent some parameter embedding optimizations. See Parameter Sniffing, Embedding, and the RECOMPILE Options under "An Embedding Restriction".

Note that this method may trigger plan warnings about implicit conversions, but they're not the kind you have to worry about. See this Q&A for background: What Triggers This Warning: Type Conversion in Expression May Affect “CardinalityEstimate” in Query Plan Choice.

In SSMS

You can change the settings to discard query results.

NUTS

SQL Query Stress

SQL Query Stress is an open source tool that allows you to run queries against a SQL Server to simulate load. No query results are returned to the application when they're run.

You can read some instructions on it here.

ostress (RML Utilities)

ostress is a similar tool, published by Microsoft, which also doesn't return results to the client, unless you choose to do it.

I've written some about it here.

Plan Explorer

SentryOne's Plan Explorer is a free alternative to view SQL Server execution plans and deadlocks with.

You can also use it as a client to query SQL Server to some degree:

NUTS

This will also discard results.

NUTS

Hope this helps!

1
  • Could you not just use the initial select to return your @End? SELECT @blob_eater = [id] ,@blob_eater = [database_id] ,@blob_eater = [proc_name] ,@blob_eater = [exec_t] from [DB].[dbo].[STAT] SELECT @End=GETDATE() Becomes SELECT @End=GETDATE() FROM [DB].[dbo].[STAT] Only the last value would be stored in the variable. Apr 15, 2019 at 16:48
1

You could execute your query with SET STATISTICS TIME ON and capture the output message by using your monitoring app on your external monitor server.

A way to capture the output message with .Net is explained in this Stack Overflow answer by AdaTheDev:

You can do this by adding an event handler to the InfoMessage event on the connection.

myConnection.InfoMessage += new SqlInfoMessageEventHandler(myConnection_InfoMessage);

void myConnection_InfoMessage(object sender, SqlInfoMessageEventArgs e)
{
    myStringBuilderDefinedAsClassVariable.AppendLine(e.Message);
}
0

This is an old question, but you could also send the results to a temp table and not actually SELECT them, like this:

DECLARE @Start datetime
DECLARE @End datetime

SELECT @StartTimeWA=GETDATE() 

DROP TABLE IF EXISTS #STAT

SELECT 
       [id] 
      ,[database_id]
      ,[proc_name]
      ,[exec_t] 
INTO #STAT
from
  [DB].[dbo].[STAT] 

SELECT @End=GETDATE()

SELECT DATEDIFF(MS,@Start,@End) AS [Duration]

That will then just return your duration value. Important note: this will be a different duration than if you had SSMS print out all the rows, particularly if you are pulling back millions of them. I am assuming your SELECT statement is really quite a bit more involved that the example you provided, and you are curious in testing purely how long does it take SQL to pull the data, and not how long it takes to travel across the network to your machine and then get displayed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.