17

I understand that the WITH RECOMPILE option forces the optimizer to rebuild the query plan for stored procs but when would you want that to happen?

What are some rules of thumb on when to use the WITH RECOMPILE option and when not to?

What's the effective overhead associated with just putting it on every sproc?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Bob Probst
  • 9,533
  • 8
  • 32
  • 41

5 Answers5

21

As others have said, you don't want to simply include WITH RECOMPILE in every stored proc as a matter of habit. By doing so, you'd be eliminating one of the primary benefits of stored procedures: the fact that it saves the query plan.

Why is that potentially a big deal? Computing a query plan is a lot more intensive than compiling regular procedural code. Because the syntax of a SQL statement only specifies what you want, and not (generally) how to get it, that allows the database a wide degree of flexibility when creating the physical plan (that is, the step-by-step instructions to actually gather and modify data). There are lots of "tricks" the database query pre-processor can do and choices it can make - what order to join the tables, which indexes to use, whether to apply WHERE clauses before or after joins, etc.

For a simple SELECT statement, it might not make a difference, but for any non-trivial query, the database is going to spend some serious time (measured in milliseconds, as opposed to the usual microseconds) to come up with an optimal plan. For really complex queries, it can't even guarantee an optimal plan, it has to just use heuristics to come up with a pretty good plan. So by forcing it to recompile every time, you're telling it that it has to go through that process over and over again, even if the plan it got before was perfectly good.

Depending on the vendor, there should be automatic triggers for recompiling query plans - for example, if the statistics on a table change significantly (like, the histogram of values in a certain column starts out evenly distributed by over time becomes highly skewed), then the DB should notice that and recompile the plan. But generally speaking, the implementers of a database are going to be smarter about that on the whole than you are.

As with anything performance related, don't take shots in the dark; figure out where the bottlenecks are that are costing 90% of your performance, and solve them first.

Ian Varley
  • 9,227
  • 5
  • 29
  • 34
  • Thanks Ian. I have not been using WITH RECOMPILE. It was in the standard sproc template at my last job(!?) but was never quite sure why. I've been spending more time recently doing some optimization and I really just wanted to get a look under the hood of this option. Thanks for all the details! – Bob Probst Jan 08 '09 at 17:02
  • I would not call it "perfectly good". If the query is in a stored procedure and takes a parameter, sql server will use parameter sniffing which can cause a "bad" execution plan to be cached (in case you didn't disable parameter sniffing..) – yakya Aug 24 '17 at 12:14
15

Putting it on every stored procedure is NOT a good idea, because compiling a query plan is a relatively expensive operation and you will not see any benefit from the query plans being cached and re-used.

The case of a dynamic where clause built up inside a stored procedure can be handled using sp_executesql to execute the TSQL rather than adding WITH RECOMPILE to the stored procedure.

Another solution (SQL Server 2005 onwards) is to use hint with specific parameters using the OPTIMIZE FOR hint. This works well if the values in the rows are static.

SQL Server 2008 has introduced a little known feature called "OPTIMIZE FOR UNKNOWN":

This hint directs the query optimizer to use the standard algorithms it has always used if no parameters values had been passed to the query at all. In this case the optimizer will look at all available statistical data to reach a determination of what the values of the local variables used to generate the queryplan should be, instead of looking at the specific parameter values that were passed to the query by the application.

Mitch Wheat
  • 295,962
  • 43
  • 465
  • 541
  • 1
    Good info on OPTIMIZE FOR UNKNOWN. I'd put all hints into the same category as WITH RECOMPILE, however. It to me has always meant I have a bad query that I need to refactor until I don't need either one. – dkretz Jan 08 '09 at 00:01
  • 4
    @dorfier: hints have there use, and yes they should be used only when absolutely required. I've seen queries that were well written but suffered from 'parameter sniffing' causing the wrong query plan to be cached. This was due to having a large number of optional params taking a wide range of values – Mitch Wheat Jan 08 '09 at 00:04
  • @mitch: which usually means to me that I should stoop to query-string concatenation. But I hate those. Usually it's a reporting requirement, of course. That's when I wish for a good QBE tool. – dkretz Jan 08 '09 at 00:15
3

generally a much better alternative to WITH RECOMPILE is OPTION(RECOMPILE) as you can see on the explanation below, taken from the answer of this question here

When a parameter-sensitivity problem is encountered, a common piece of advice on forums and Q&A sites is to "use recompile" (assuming the other tuning options presented earlier are unsuitable). Unfortunately, that advice is often misinterpreted to mean adding WITH RECOMPILE option to the stored procedure.

Using WITH RECOMPILE effectively returns us to SQL Server 2000 behaviour, where the entire stored procedure is recompiled on every execution. A better alternative, on SQL Server 2005 and later, is to use the OPTION (RECOMPILE) query hint on just the statement that suffers from the parameter-sniffing problem. This query hint results in a recompilation of the problematic statement only; execution plans for other statements within the stored procedure are cached and reused as normal.

Using WITH RECOMPILE also means the compiled plan for the stored procedure is not cached. As a result, no performance information is maintained in DMVs such as sys.dm_exec_query_stats. Using the query hint instead means that a compiled plan can be cached, and performance information is available in the DMVs (though it is limited to the most recent execution, for the affected statement only).

For instances running at least SQL Server 2008 build 2746 (Service Pack 1 with Cumulative Update 5), using OPTION (RECOMPILE) has another significant advantage over WITH RECOMPILE: only OPTION (RECOMPILE) enables the Parameter Embedding Optimization.

Community
  • 1
  • 1
Marcello Miorelli
  • 3,368
  • 4
  • 44
  • 67
2

The most common use is when you might have a dynamic WHERE clause in a procedure...you wouldn't want that particular query plan to get compiled and saved for subsequent executions because it very well might not be the exact same clause the next time the procedure is called.

Gunny
  • 1,146
  • 7
  • 11
1

It should only be used when testing with reprentative data and context demonstrate that doing without produces invalid query plans (whatever the possible reasons might be). Don't assume beforehand (without testing) that an SP won't optimize properly.

Sole exception for manual invocation only (i.e. don't code it into the SP): When you know that you've substantially altered the character of the target tables. e.g. TRUNCATE, bulk loads, etc.

It's yet another opportunity for premature optimization.

halfer
  • 19,824
  • 17
  • 99
  • 186
dkretz
  • 37,399
  • 13
  • 80
  • 138
  • @le dorfier: I disagree. It should only be used when there are no other options available. I ceratinly wouldn't recommend using it during testing, when your test data is likely to be unrepresentative of the production environment. – Mitch Wheat Jan 07 '09 at 23:53
  • Then I was unclear and we agree. I meant that, if testing repeatedly shows anomolous optimization on representative data, then you may need to build it in (and then only until you figure out what's messing up the anomalies). There's a Question in play now where that's the case. – dkretz Jan 07 '09 at 23:58