I have two almost identical queries running on the same SQL Server 2005 instance:
- The first one is the original
SELECT
query as generated by LINQ (I know, I know… I'm not the application developer, just the DBA :). - The second one is exactly the same as the first one, added a
OPTION (RECOMPILE)
at the end.
Nothing else has been changed.
The first one takes 55 seconds everytime its run.
The second one takes 2 seconds.
Both result sets are identical.
Why would this hint generate such a dramatic gain in performance?
The Books Online entry on RECOMPILE
doesn't offer a much detailed explanation:
Instructs the SQL Server Database Engine to discard the plan generated
for the query after it executes, forcing the query optimizer to
recompile a query plan the next time the same query is executed.
Without specifying RECOMPILE, the Database Engine caches query plans
and reuses them. When compiling query plans, the RECOMPILE query hint
uses the current values of any local variables in the query and, if
the query is inside a stored procedure, the current values passed to
any parameters.RECOMPILE is a useful alternative to creating a stored procedure that
uses the WITH RECOMPILE clause when only a subset of queries inside
the stored procedure, instead of the whole stored procedure, must be
recompiled. For more information, see Recompiling Stored Procedures.
RECOMPILE is also useful when you create plan guides. For more
information, see Optimizing Queries in Deployed Applications by Using
Plan Guides.
Since my query has a lot of local variables, my guess is that SQL Server is able to (seriously) optimize it when I use the OPTION (RECOMPILE)
query hint.
Everywhere I look people are saying that OPTION (RECOMPILE)
should be avoided. The explanation for this is generally that using this hint SQL Server is not able to reuse this exection plan and therefore has to waste time recompiling it everytime.
(But) Given the gigantic performance advantage, I'm inclined to think that using this query hint this time would be a good thing.
Should I use it?
If not, is there a way I can force SQL Server to use a better execution plan without this hint and without altering the application?
Best Answer
As documented in the article Statistics Used by the Query Optimizer in Microsoft SQL Server 2005
When the optimiser has no usable statistics at all for a column it will guess that an
=
predicate will match 10% of rows,BETWEEN
9%, and any of>, >=, < and <=
will match 30%. If there are column statistics available an=
predicate will be treated differently as below.So this is essentially the same as using for
OPTIMIZE FOR (UNKNOWN)
. It may well be more accurate than a flat10%
guess but it isn't tailored to the specific values that you are querying.With the use of
RECOMPILE
you presumably are getting more accurate cardinality estimates and therefore a different plan with join orders/ join types more suited to the number of rows returned from different parts of your actual query.