views:

1079

answers:

3

Your basic SP with a default parameter:

ALTER PROCEDURE [usp_debug_fails]
    @DATA_DT_ID AS int = 20081130
WITH RECOMPILE
AS
BEGIN
    /*
        Usage:
        EXEC [usp_debug_fails] WITH RECOMPILE
    */
    -- Stuff here that depends on DATA_DT_ID
END

The same SP with a local that is hardcoded.

ALTER PROCEDURE usp_debug_works]
WITH RECOMPILE
AS
BEGIN
    /*
        Usage:
        EXEC [usp_debug_works] WITH RECOMPILE
    */

    DECLARE @DATA_DT_ID AS int
    SET @DATA_DT_ID = 20081130
    -- Stuff here that depends on DATA_DT_ID
END

You can see where I put in the (redundant, even) WITH RECOMPILE options in order to avoid parameter sniffing (this was never necessary in development where this thing worked fine)

The one that works completes fine in a minute or two, the other never completes - just sits there for hours.

This problem never happened on the development server (build 9.00.3282.00), the production server is build 9.00.3068.00

I've removed all kinds of code from the procs to try to get down to the minimal version which still exhibits the problem, and have been very careful to keep both versions of the SP the same except for that one parameter.

I have plenty of other SPs which take parameters and they do run fine. I've also DROPped and reCREATEed the SPs.

Any ideas?

And yes, I have a DBA looking at it and I do not have SHOWPLAN or any useful rights on production to see if there is blocking (in case one's plan results in a lock escalation I guess - again, the only difference is the parameter)

I've reviewed all the SQL Server build information and don't see a known issue about this, so until I figure it out or the DBA figures it out, I'm kind of stuck.

UPDATE

This also fails to complete (this is actually the normal form for these SPs - I just put a default in to make it easier to switch back and forth during testing)

ALTER PROCEDURE [usp_debug_fails]
    @DATA_DT_ID AS int
WITH RECOMPILE
AS
BEGIN
    /*
        Usage:
        EXEC [usp_debug_fails] 20081130 WITH RECOMPILE
    */
    -- Stuff here that depends on DATA_DT_ID
END

however this one completes (which may work as a workaround, although I have about 25 of these SPs to modify which all have the same form):

ALTER PROCEDURE [usp_debug_fails]
    @DATA_DT_ID_in AS int
WITH RECOMPILE
AS
BEGIN
    /*
        Usage:
        EXEC [usp_debug_fails] 20081130 WITH RECOMPILE
    */

    DECLARE @DATA_DT_ID AS int
    SET @DATA_DT_ID = @DATA_DT_ID_in
    -- Stuff here that depends on DATA_DT_ID
END
+2  A: 

Try masking the input parameter.

I guess the recompile isn't working because of the specified default (EDIT: Or parameter sent on first call) being sniffed at compile time. So, recompile has no effect.

I've seen huge difference between estimated plans simply by changing the default from say, zero to NULL, or not having one.

ALTER PROCEDURE [usp_debug_mightwork]
    @DATA_DT_ID AS int = 20081130
AS
BEGIN
    DECLARE @IDATA_DT_ID AS int
    SET @IDATA_DT_ID = @DATA_DT_ID
    -- Stuff here that depends on IDATA_DT_ID
END

I think this article explains...

...parameter values are sniffed during compilation or recompilation...

EDIT:

New link on query plans and parameters. It's still parameter sniffing whether a default is specified or not.

The WITH RECOMPILE option specified on the GetRecentSales stored procedure above does not eliminate the cardinality estimation error

Kind of related article about constants and plans

gbn
The parameter masking appears to work. The default, however, doesn't seem to be the primary cause - I have updated my question with what is known so far.
Cade Roux
Added more links
gbn
Is it likely that problem only exists in certain builds? It never happened in development. Why does it make such a huge difference (and not complete) regardless of choice of DATA_DT_ID, the cardinality in all tables is similar? Why even when the SP is DROPed. i.e. Is it really a bug in SQL Srv?
Cade Roux
If the SP is dropped, it may not be forced out of cache if it's in use. I can't find my article on it.The second option is that stats or fragmentation may be different on the servers because of the load differenceDrop all stats and rebuild all indexes, or restore prod onto dev and run the code
gbn
I regularly see prod vs dev differences even though all boxes have same OS and SQL build with similar hardware specs too.
gbn
DBA came back with same solution - this is a huge bug in this build, but the build is out of date, so whatever, I guess. Ultimately, the client is not going to be able to maintain this system if it requires this level of workarounds - they don't understand SQl Server that well.
Cade Roux
A: 

Prevent parameter sniffing or you are toast when statistics change. I have 500+ sps and all of them start with:

DECLARE @_Param1 ..., @_ParamN

--- prevent pameter sniffing
SELECT @_Param1 = @Param1, @_ParamN = @ParamN

cheers,
</wqw>

wqw
That's fine, except this is a new sproc in the database AND all parameter values have equivalent data distribution AND it's not a case of the process taking a little longer - it NEVER completes.
Cade Roux
A: 

What was the solution to this issue? I face a similar issue and cant seem to find a solution. The stored procedure executes perfectly find in dev environment. It does not execute completely on the production environment.

Appreciate your guidance

Tasneem
The problem was primarily parameter sniffing. Have a look at the execution plans. Update the statistics, prevent parameter sniffing with parameter masking, WITH RECOMPILE or OPTIMIZE FOR UNKNOWN (2008).
Cade Roux