SP taking 15 minutes, but the same query when executed returns results in 1-2 minutes
Asked Answered
P

11

36

So basically I have this relatively long stored procedure. The basic execution flow is that it SELECTS INTO some data into temp tables declared with the # sign and then runs a cursor through these tables to generate a 'running total' into a third temp table which is created using CREATE. Then this resulting temp table is joined with other tables in the DB to generated the result after some grouping etc. The problem is, this SP had been running fine until now returning results in 1-2 minutes. And now, suddenly, its taking 12-15 minutes. If I extract the query from the SP and executed it in management studio by manually setting the same parameters, it returns results in 1-2 minutes but the SP takes very long. Any idea what could be happening? I tried to generate the Actual Execution plans of both the query and the SP but it couldn't generate it because of the cursor. Any idea why the SP takes so long while the query doesn't?

Polyanthus answered 12/8, 2009 at 9:52 Comment(1)
Does your SP have parameters?Haplography
H
78

This is the footprint of parameter-sniffing. See here for another discussion about it; SQL poor stored procedure execution plan performance - parameter sniffing

There are several possible fixes, including adding WITH RECOMPILE to your stored procedure which works about half the time.

The recommended fix for most situations (though it depends on the structure of your query and sproc) is to NOT use your parameters directly in your queries, but rather store them into local variables and then use those variables in your queries.

Haplography answered 12/8, 2009 at 13:55 Comment(8)
wow ! Thanks RBarry Young ! .. I just modified my proc to use a local variable instead of parameter and the proc went from 10 seconds to 0 seconds !Egregious
This happens when a stored procedure differs widly depending on either, what parameters are passed or when it is run. Some previously calculated query plan ends up being totally wrong for the next execution. The best solution is to remove these variations from the stored procedures. If WITH RECOMPILE is helping, then there is no point in using a stored procedure. They exist for performance, not structured programming. If you want to do two different things, make two stored procedures.Burkes
@Burkes While the first part of your comment is correct, the last part is not. Stored procedures serve several purposes in SQL Server and performance is not even the most important one.Haplography
okay, they can also be useful for security. I'd still assert, if you want to do two different things, make two stored procedures.Burkes
Often run into parameter sniffing when using Date parameters. Converting my input param to a local param to use throughout my query is often the solution as stated above.Thearchy
Its not working for me taking same time to execute even after fix the parameter sniffing issuesStereoscopic
This works but feels dirty. It seems logical to use your parameters in your query, transferring their values just doesn't make sense to me. I read that article and it did not clear things up. Maybe I should just stick to code but no one wants to hire DBAs anymore.Ralline
@Zoey This was a workaround for earlier versions of SQL Server. Later versions are much less susceptible to parameter-sniffing problems, and the RECOMPILE bug has been corrected so that it’s now the recommended fix when it does happen.Haplography
D
14

its due to parameter sniffing. first of all declare temporary variable and set the incoming variable value to temp variable and use temp variable in whole application here is an example below.

ALTER PROCEDURE [dbo].[Sp_GetAllCustomerRecords]
@customerId INT 
AS
declare @customerIdTemp INT
set @customerIdTemp = @customerId
BEGIN
SELECT * 
FROM   Customers e Where
CustomerId = @customerIdTemp 
End

try this approach

Disyllable answered 6/3, 2014 at 11:2 Comment(2)
+1 because this solved my issue. The sproc had one int input parameter. When I copied it to a local variable and used that in the following queries - Voila!Selfsustaining
This worked great for me - brought a stored procedure from 12 minutes to 5 seconds.Galenic
C
2

Try recompiling the sproc to ditch any stored query plan

exec sp_recompile 'YourSproc'

Then run your sproc taking care to use sensible paramters.

Also compare the actual execution plans between the two methods of executing the query.

It might also be worth recomputing any statistics.

Concourse answered 12/8, 2009 at 10:3 Comment(0)
D
2

I'd also look into parameter sniffing. Could be the proc needs to handle the parameters slighlty differently.

Detection answered 12/8, 2009 at 13:24 Comment(0)
L
1

I usually start troubleshooting issues like that by using "print getdate() + ' - step '". This helps me narrow down what's taking the most time. You can compare from where you run it from query analyzer and narrow down where the problem is at.

Lecce answered 12/8, 2009 at 14:0 Comment(1)
I like this as a quick and easy traceVantassel
P
0

This is because of parameter snipping. But how can you confirm it?

Whenever we supposed to optimize SP we look for execution plan. But in your case, you will see an optimized plan from SSMS because it's taking more time only when it called through Code.

For every SP and Function, the SQL server generates two estimated plans because of ARITHABORT option. One for SSMS and second is for the external entities(ADO Net).

ARITHABORT is by default OFF in SSMS. So if you want to check what exact query plan your SP is using when it calls from Code.

Just enable the option in SSMS and execute your SP you will see that SP will also take 12-13 minutes from SSMS. SET ARITHABORT ON EXEC YourSpName SET ARITHABORT OFF

To solve this problem you just need to update the estimate query plan.

There are a couple of ways to update the estimate query plan. 1. Update table statistics. 2. recompile SP 3. SET ARITHABORT OFF in SP so it will always use query plan created for SSMS (this option is not recommended) For more options please refer to this awesome article - http://www.sommarskog.se/query-plan-mysteries.html

Parvis answered 12/8, 2009 at 9:52 Comment(0)
L
0

I would guess it could possible be down to caching. If you run the stored procedure twice is it faster the second time?

To investigate further you could run them both from management studio the stored procedure and the query version with the show query plan option turned on in management studio, then compare what area is taking longer in the stored procedure then when run as a query.

Alternativly you could post the stored procedure here for people to suggest optimizations.

Lawana answered 12/8, 2009 at 10:2 Comment(0)
S
0

For a start it doesn't sound like the SQL is going to perform too well anyway based on the use of a number of temp tables (could be held in memory, or persisted to tempdb - whatever SQL Server decides is best), and the use of cursors.

My suggestion would be to see if you can rewrite the sproc as a set-based query instead of a cursor-approach which will give better performance and be a lot easier to tune and optimise. Obviously I don't know exactly what your sproc does, to give an indication as to how easy/viable this is for you.

As to why the SP is taking longer than the query - difficult to say. Is there the same load on the system when you try each approach? If you run the query itself when there's a light load, it will be better than when you run the SP during a heavy load.

Also, to ensure the query truly is quicker than the SP, you need to rule out data/execution plan caching which makes a query faster for subsequent runs. You can clear the cache out using:

DBCC FREEPROCCACHE
DBCC DROPCLEANBUFFERS

But only do this on a dev/test db server, not on production. Then run the query, record the stats (e.g. from profiler). Clear the cache again. Run the SP and compare stats.

Spleenful answered 12/8, 2009 at 10:5 Comment(1)
Running totals is one of the few times when using a cursor may be faster than set-based code.Detection
L
0

1) When you run the query for the first time it may take more time. One more point is if you are using any corellated sub query and if you are hardcoding the values it will be executed for only one time. When you are not hardcoding it and run it through the procedure and if you are trying to derive the value from the input value then it might take more time.

2) In rare cases it can be due to network traffic, also where we will not have consistency in the query execution time for the same input data.

Luciennelucier answered 12/8, 2009 at 10:7 Comment(0)
N
0

I too faced a problem where we had to create some temp tables and then manipulating them had to calculate some values based on rules and finally insert the calculated values in a third table. This all if put in single SP was taking around 20-25 min. So to optimize it further we broke the sp into 3 different sp's and the total time now taken was around 6-8 mins. Just identify the steps that are involved in the whole process and how to break them up in different sp's. Surely by using this approach the overall time taken by the entire process will reduce.

Nessy answered 17/11, 2010 at 10:1 Comment(0)
F
-1

I would suggest the issue is related to the type of temp table (the # prefix). This temp table holds the data for that database session. When you run it through your app the temp table is deleted and recreated.
You might find when running in SSMS it keeps the session data and updates the table instead of creating it. Hope that helps :)

Frilling answered 12/8, 2009 at 9:57 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.