Dropping a cached plan?

  • Greetings all!

    I have a stored procedure I am developing (for quite a while now). I am sure after testing several thousand times it had generated quite a few plans that are no longer the best suited for what I have now.

    If I run it with option(recompile) it generates a much more efficient plan however, taking this option out it uses the old plan again. Is there a way to force this to use the plan it creates with the option(recompile) ?

    Link to my blog http://notyelf.com/

  • shannonjk (12/2/2009)


    I am sure after testing several thousand times it had generated quite a few plans that are no longer the best suited for what I have now.

    There will only ever be at most two plans for a procedure in cache. One serial, one parallel. (ignoring the possibility of different set options from different clients)

    If I run it with option(recompile) it generates a much more efficient plan however, taking this option out it uses the old plan again. Is there a way to force this to use the plan it creates with the option(recompile) ?

    Post the procedure and the two execution plans please?

    If you run sp_recompile 'Procedure Name' and then run the proc again without WITH RECOMPILE, do you get a good plan?

    Gail Shaw
    Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
    SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability

    We walk in the dark places no others will enter
    We stand on the bridge and no one may pass
  • Gail's already focused on the core of the question, you're only going to see two plans in the cache for a given query (assuming the same parameters, yada-yada).

    But, you can drop a specific plan. You just need to do this:

    --First get the plan handle

    SELECT decp.plan_handle

    FROM sys.dm_exec_cached_plans AS decp

    CROSS APPLY sys.dm_exec_sql_text(decp.plan_handle) AS dest

    WHERE dest.[text] LIKE 'CREATE PROC dbo.spAddressByCity%'; -- or some other comparison to identify your query

    --then drop the plan

    DBCC freeproccache(0x05000E000A70051EB8A0A309000000000000000000000000);

    But honestly, that's not applicable to your situation.

    "The credit belongs to the man who is actually in the arena, whose face is marred by dust and sweat and blood"
    - Theodore Roosevelt

    Author of:
    SQL Server Execution Plans
    SQL Server Query Performance Tuning

  • Sorry for the delayed response on this!

    I believe I figured out the problem. Here is what I believe was the issue; The stored proc is used for reporting service reports. There are 8 parameters that can be defined however the script, the first 6 are very high level only slightly shifting the report in a company-wide type reporting structure. The last 2 parameters filter the report down to agencies and people. I realize that 2 plans are needed, 1 to satisfy the high level and a 2nd to satisfy the finite report. If I do the sp_recompile and run the finite report, it runs great, but the high level runs poorly. If I redo the sp_recompile and run the high level report, then it runs great but the finite report runs slow.

    Outside of just splitting the stored proc out into 2 separate ones (thus needing to create 2 separate reports), is there a way to work around this? I really don't want to add option(recompile) to my proc...

    Link to my blog http://notyelf.com/

  • You've effectively written two different queries, and yeah, each query needs a different execution plan. Recompile is probably your best option.

    "The credit belongs to the man who is actually in the arena, whose face is marred by dust and sweat and blood"
    - Theodore Roosevelt

    Author of:
    SQL Server Execution Plans
    SQL Server Query Performance Tuning

  • Try splitting into two procedures, but no need for two reports. Have the report call a wrapper proc that checks the parameters and calls one of two procedures to do the actual work.

    Something like this

    CREATE PROCEDURE OuterProcedure (@Param1 .... @Param8)

    IF @Param7 IS NULL AND @Param8 IS NULL

    EXEC HighLevelReport @Param1 ... @Param6

    ELSE

    EXEC DetailedReport @Param1 .... @Param8

    That's rough semi-pseudocode, but should give you the idea.

    These may be worth reading too:

    http://sqlinthewild.co.za/index.php/2009/09/15/multiple-execution-paths/

    http://sqlinthewild.co.za/index.php/2009/03/19/catch-all-queries/

    Gail Shaw
    Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
    SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability

    We walk in the dark places no others will enter
    We stand on the bridge and no one may pass
  • Awesome idea Gail thanks!

    Thank you for the links as well, they were very helpful!

    Link to my blog http://notyelf.com/

  • Gail,

    On your second link when you wrote about the Dynamic SQL; I really like that idea however my code is a little over 10k characters and parametrized

    I have been looking for the last hour or so and I can not find an intuitive work around to this.

    Any ideas?

    Link to my blog http://notyelf.com/

  • Do you really need dynamic SQL? Your question indicated there were two possibilities - the detailed and the high level report. If that's the case, use if - else with two procedures. Dynamic SQL's great when there are two many possible queries to do if - else blocks with

    Gail Shaw
    Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
    SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability

    We walk in the dark places no others will enter
    We stand on the bridge and no one may pass
  • Not this one necessarily, but I have several Stored procedures that are similar to this vien, some of them have multiple variations that I would like to test the viability of dynamic SQL on these more variable stored procs 😀

    Link to my blog http://notyelf.com/

  • Just be aware that dynamic SQL can lead to the exact same types of problems you were facing with this procedure. It's worth knowing ahead of time. The one way you can minimize the issues, but not eliminate them, is to use parameterized queries in the dynamic SQL, meaning don't build a SQL string and run it using exec. Look up sp_executesql and learn how to pass it parameters. Then you build the dynamic SQL with paramters and you'll get more consistent plans and some plan reuse.

    "The credit belongs to the man who is actually in the arena, whose face is marred by dust and sweat and blood"
    - Theodore Roosevelt

    Author of:
    SQL Server Execution Plans
    SQL Server Query Performance Tuning

  • Thanks Grant 🙂

    I know how to use sp_executesql and pass parameters through that. My only issue is getting around the character limit for my more robust queries 🙂

    Link to my blog http://notyelf.com/

  • shannonjk (12/7/2009)


    Thanks Grant 🙂

    I know how to use sp_executesql and pass parameters through that. My only issue is getting around the character limit for my more robust queries 🙂

    Assuming 2005/2008, use VARCHAR(MAX).

    "The credit belongs to the man who is actually in the arena, whose face is marred by dust and sweat and blood"
    - Theodore Roosevelt

    Author of:
    SQL Server Execution Plans
    SQL Server Query Performance Tuning

  • Varchar(max) isn't acceptable because it has to be nVarchar(Max). But that still has a character limit I have surpassed.

    Is there not another way to get around that?

    Link to my blog http://notyelf.com/

  • nVarchar(max) only has a size limit, not a character limit and we're talking gb's, so you shouldn't be hitting that limit (not saying you're not, but you sure shouldn't be).

    "The credit belongs to the man who is actually in the arena, whose face is marred by dust and sweat and blood"
    - Theodore Roosevelt

    Author of:
    SQL Server Execution Plans
    SQL Server Query Performance Tuning

Viewing 15 posts - 1 through 15 (of 18 total)

You must be logged in to reply to this topic. Login to reply