• subscribe
March 16, 2011 07:02 AM

Fine-Tuning Plan Reuse

Two options to tweak performance
SQL Server Pro
InstantDoc ID #129462

I’m a big advocate of trying to get as much query plan reuse as possible. By plan reuse, I’m talking about SQL Server’s ability to reuse an already existing plan in the procedure cache to run a newly executed query that’s similar in nature. Reusing an already compiled plan instead of compiling a completely new plan can save a considerable amount of time and resources.

The queries that most often don’t reuse an existing plan are those generated dynamically by the client or the middle tier of an application. These types of queries are referred to as ad hoc queries or ad hoc batches. Many of them don’t attempt to use parameters in any way and essentially hard-code all of the queries’ literal values. But the most common offense is not using parameters in the search arguments (SARGs) of WHERE clauses.

Fortunately, two SQL Server options can help alleviate some of the pains associated with lack of plan reuse caused by applications that weren’t written with plan reuse in mind. Before I tell you about these options, though, it’s helpful to know the basics about the procedure cache process.

 

Procedure Cache Basics

Each time SQL Server gets a request to run an ad hoc query, it must first look through the existing plans in the procedure cache to see if one already exists. After using a hash routine to narrow down the list, SQL Server ends up doing a character-by-character, case- and space-sensitive comparison of the new batch against existing batches. A single character or literal value difference will result in a mismatch. If SQL Server finds an exact match, it uses the existing plan to execute the new batch. If it doesn’t find an exact match, SQL Server parses and compiles a new plan and places that plan in the cache before it uses the new plan to execute the query. For more details on how this process works, see the excellent white paper “Plan Caching in SQL Server 2008”.

If there are lots of similar plans already in the procedure cache, the query lookup process can be quite resource intensive. So is compiling and optimizing a new plan for each batch that doesn’t have an exact match. This also results in yet another query plan placed into the cache, which uses up vital memory and potentially makes the next query lookup process even more resource intensive.

 

Option 1

By default, SQL Server tries to find a way to make ad hoc queries reuse previous plans, which is referred to as auto-parameterization. When a batch has been auto-parameterized, some or all of the statements’ literal values get replaced with a parameter. So, it essentially takes an ad hoc batch that looks like

SELECT * FROM Customers

  WHERE CustID = 652837;

SELECT * FROM Customers

  WHERE CustID = 843762;

and turns it into

DECLARE @p1 INT;

  SET @p1 = 652837;

  SELECT * FROM Customers

  WHERE CustID = @p1;

DECLARE @p1 INT;

  SET @p1 = 843762;

  SELECT * FROM Customers

  WHERE CustID = @p1;

(Note that if you were to run this ad hoc batch and view the auto-parameterized statements in SQL Server Profiler, they won’t be the same as shown here. I added the parameter assignments to better get the point across.) Now when SQL Server attempts to find a similar query plan in the cache, it looks at the parameterized version of the query (minus the parameter assignments). It’ll find a match each time a subsequent similar parameterized batch is called and reuse the previously existing plan. The result is a far more efficient use of resources and a better performing system overall.



ARTICLE TOOLS

Comments
  • gunneyk
    10 months ago
    Jul 30, 2011

    Harry,

    Yes the plans are memory resident only and will be lost if you restart SQL Server. However restarting SQL Server should be a rare occurance.

    Andy

  • hvdtol
    11 months ago
    Jun 14, 2011

    Andy,

    Thank for the information.
    My point is that the plan is stored in cache in stead of a location in the database.
    Whenver Sql Server has been restarted the information is lost.
    Or am i wrong?

    Harry

  • gunneyk
    1 year ago
    Apr 15, 2011

    Harry,
    The only suggestion to tweak code is when you make calls that do not allow for plan reuse and cannot be overcome with the two options listed. It is not a matter of getting a better plan it is all about reusign the existing ones. Getting a better plan is a whole different story. But if you don't get plan reuse then you waste a lot of time & resources compiling new plans each time you make the call to the database. At present SQL Server doesn't have the option to change any of the existing plans in the cache other than to mark them for recompile. The point here is that is you are not getting plan reuse you can turn on one of the two options listed to try and get better plan reuse with the FORCE PARAMETERIZATON option or to minimize the impact of the plans that don't get reused with the OPTIMIZE FOR ADHOC WORKLOAD option. Neither of those options requires any changes in code. I hope that is more clear.

    Andy

  • hvdtol
    1 year ago
    Apr 04, 2011

    I'm a DBA for Sql Server and Oracle, so i am able to compare.
    I this matter, Microsoft can learn from Oracle.

    Since their latest version 11g, Oracle stores each executed plan in the database.
    Whenever the same query comes along, the same plan is is being used.
    A nightly tuning task, looks for better plans from queries executed during the day, and stored it in the database, which can be used next time the query runs.

    This is much more effecient then tweeking the code, as this article suggests.

    Harry

You must log on before posting a comment.

Are you a new visitor? Register Here