39

I am doing some tests using the SQL 2005 profiler.

I have a stored procedure which simply runs one SQL query.

When I run the stored procedure, it takes a long time and performs 800,000 disk reads.

When I run the same query separate to the stored procedure, it does 14,000 disk reads.

I found that if I run the same query with OPTION(recompile), it takes 800,000 disk reads.

From this, I make the (possibly erroneous) assumption that the stored procedure is recompiling each time, and that's causing the problem.

Can anyone shed some light onto this?

I have set ARITHABORT ON. (This solved a similar problem on stackoverflow, but didn't solve mine)

Here is the entire stored procedure:

CREATE PROCEDURE [dbo].[GET_IF_SETTLEMENT_ADJUSTMENT_REQUIRED]
 @Contract_ID int,
 @dt_From smalldatetime,
 @dt_To smalldatetime,
 @Last_Run_Date datetime
AS
BEGIN
 DECLARE @rv int


 SELECT @rv = (CASE WHEN EXISTS
 (
  select * from 
  view_contract_version_last_volume_update
  inner join contract_version
  on contract_version.contract_version_id = view_contract_version_last_volume_update.contract_version_id
  where contract_version.contract_id=@Contract_ID
  and volume_date >= @dt_From
  and volume_date < @dt_To
  and last_write_date > @Last_Run_Date
 )
 THEN 1 else 0 end)

 -- Note that we are RETURNING a value rather than SELECTING it.
 -- This means we can invoke this function from other stored procedures
 return @rv
END

Here's a script I run that demonstrates the problem:

DECLARE 
 @Contract_ID INT,
 @dt_From smalldatetime,
 @dt_To smalldatetime,
 @Last_Run_Date datetime,
    @rv int


SET @Contract_ID=38
SET @dt_From='2010-09-01'
SET @dt_To='2010-10-01'
SET @Last_Run_Date='2010-10-08 10:59:59:070'


-- This takes over fifteen seconds
exec GET_IF_SETTLEMENT_ADJUSTMENT_REQUIRED @Contract_ID=@Contract_ID,@dt_From=@dt_From,@dt_To=@dt_To,@Last_Run_Date=@Last_Run_Date

-- This takes less than one second!
SELECT @rv = (CASE WHEN EXISTS
(
 select * from 
 view_contract_version_last_volume_update
 inner join contract_version
 on contract_version.contract_version_id = view_contract_version_last_volume_update.contract_version_id
 where contract_version.contract_id=@Contract_ID
 and volume_date >= @dt_From
 and volume_date < @dt_To
 and last_write_date > @Last_Run_Date
)
THEN 1 else 0 end)


-- With recompile option. Takes 15 seconds again!
SELECT @rv = (CASE WHEN EXISTS
(
 select * from 
 view_contract_version_last_volume_update
 inner join contract_version
 on contract_version.contract_version_id = view_contract_version_last_volume_update.contract_version_id
 where contract_version.contract_id=@Contract_ID
 and volume_date >= @dt_From
 and volume_date < @dt_To
 and last_write_date > @Last_Run_Date
)
THEN 1 else 0 end) OPTION(recompile)
Andrew Shepherd
  • 44,254
  • 30
  • 139
  • 205

7 Answers7

82

OK, we have had similar issues like this before.

The way we fixed this, was by making local parameters inside the SP, such that

DECLARE @LOCAL_Contract_ID int, 
        @LOCAL_dt_From smalldatetime, 
        @LOCAL_dt_To smalldatetime, 
        @LOCAL_Last_Run_Date datetime

SELECT  @LOCAL_Contract_ID = @Contract_ID, 
        @LOCAL_dt_From = @dt_From, 
        @LOCAL_dt_To = @dt_To, 
        @LOCAL_Last_Run_Date = @Last_Run_Date

We then use the local parameters inside the SP rather than the parameters that was passed in.

This typically fixed the issue for Us.

We believe this to be due to parameter sniffing, but do not have any proof, sorry... X-)

EDIT:

Have a look at Different Approaches to Correct SQL Server Parameter Sniffing for some insightful examples, explanations and fixes.

Adriaan Stander
  • 162,879
  • 31
  • 289
  • 284
  • 4
    And now the stored procedure goes so fast it has 0 duration in the profiler. Unbelievable. Should I be worried about Cargo Cult Programming? Right now I'm just overjoyed it's fixed. :-) – Andrew Shepherd Oct 22 '10 at 11:18
  • 2
    This also fixed my issue. Not really sure how this make any since. Query ran in 7 secs and stored procedure took over 7 mins. Using Local Variables it runs in 6 secs. Thanks! – buzzzzjay May 15 '13 at 17:22
  • 2
    I burn my 2 days for increase performance of my store procedure, it took 1 min & 20 second for execution but once i change it complete with just 3 sec. Thanks! :) – Hitusam Mar 01 '17 at 03:22
  • 1
    applied OPTION(RECOMPILE) on slow/awkward query improved things a lot – Adeem Jul 10 '17 at 10:56
  • This worked for me as well! I have been trying to figure out, what the hell is happening. Phew! Now I am trying to find out, why this works. Anyone, any suggestions? – Praneet Nadkar Apr 11 '19 at 12:28
  • 1
    Still as relevant on SQL Server 2016 as in 2005! – zatbusch Dec 19 '19 at 08:23
  • 2023, this saved my afternoon – nun3z Jan 06 '23 at 14:12
9

As others have mentioned, this could be a 'parameter sniffing' problem. Try including the line:

OPTION (RECOMPILE)

at the end of your SQL query.

There is an article here explaining what parameter sniffing is: http://blogs.technet.com/b/mdegre/archive/2012/03/19/what-is-parameter-sniffing.aspx

ninjaPixel
  • 6,122
  • 3
  • 36
  • 47
  • 1
    +1 - it was for us, we followed the answer given by [Adam Marshall](http://stackoverflow.com/users/134653/adam-marshall) in [SO: SQL Server: Query fast, but slow from procedure](http://stackoverflow.com/questions/440944/sql-server-query-fast-but-slow-from-procedure) and it reduced our sp runtime from **20 MINUTES** to **4 SECONDS** – Our Man in Bananas Jun 18 '14 at 15:35
5

I guess this is caused by parameter sniffing.

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Giorgi
  • 30,270
  • 13
  • 89
  • 125
  • 1
    +1 - it was for us, we followed the answer given by [Adam Marshall](http://stackoverflow.com/users/134653/adam-marshall) in [SO: SQL Server: Query fast, but slow from procedure](http://stackoverflow.com/questions/440944/sql-server-query-fast-but-slow-from-procedure) and it reduced our sp runtime from **20 MINUTES** to **4 SECONDS** – Our Man in Bananas Jun 18 '14 at 15:34
4

The issue of why a batch takes forever to run inside a SQL stored procedure yet runs instantaneously in SSMS has to do with SQL parameter sniffing, especially with datetime parameters.

There are several excellent articles on parameter sniffing out there.

Here's one of them ( I didn't write it, just passing it on).

http://www.sommarskog.se/query-plan-mysteries.html

Brian Webster
  • 30,033
  • 48
  • 152
  • 225
user1472721
  • 191
  • 1
  • 2
3

On my issue I've run:

exec sp_updatestats 

and this speed up my sp from 120s to just 3s. More info about Updating Statistics can be found here https://msdn.microsoft.com/en-us/library/ms173804.aspx

alaneo
  • 89
  • 4
2

I too got the same problem today. I have dropped and recreated the SP and it worked. This is something with SP cache and when dropped the SP the cached plan has been removed. You can try the same or use 'DBCC FREEPROCCACHE' to delete cache.

SumanKumar
  • 344
  • 5
  • 19
0

My store producture executed time 2 mins 45 secs and above. then used OPTION (RECOMPILE) Now same producture executed time5 to 7 sec

Try this : OPTION (RECOMPILE);

CREATE PROCEDURE YourProcedure 
@Parameter INT
AS
BEGIN
SELECT * FROM YourTable
WHERE YourColumn = @Parameter    
OPTION (RECOMPILE);
END