Forced Parameterization
In SQL Server 2008, if a
SQL statement is executed without parameters, the Query Optimizer
parameterizes the statement internally to increase the possibility of
matching it against an existing execution plan. This process is called simple parameterization,
sometimes referred to as auto-parameterization. Simple parameterization
is somewhat limited in that it can parameterize only a relatively small
number of queries that match a small number
of very simple and strictly defined query templates. For example,
simple parameterization is not possible for queries that contain any of
the following query elements:
References to more than one table
IN clauses or OR expressions
UNION
Any query hints
DISTINCT
TOP
Subqueries
GROUP BY
Not equal (<> or !=) comparisons
References to functions
SQL Server 2008 enables
you to override the default simple parameterization behavior of SQL
Server and provide parameterization for more complex queries by
specifying that all SELECT, INSERT, UPDATE, and DELETE
statements in a database be implicitly parameterized when they are
compiled by the Query Optimizer. You enable this by setting the PARAMETERIZATION option to FORCED in the ALTER DATABASE statement:
ALTER DATABASE dbname SET PARAMETERIZATION {FORCED | SIMPLE}
Setting the PARAMETERIZATION option is an online operation that can be issued at any time and requires no database-level exclusive locks.
Forced parameterization
may improve the performance of queries for certain databases by
reducing the frequency of query compilations and recompilations.
Essentially, forced parameterization provides the query plan reuse
benefits of parameterized queries without requiring you to rewrite a
single line of application code. The databases that may benefit from
forced parameterization generally support OLTP-type applications that
experience high volumes of concurrent queries, such as point-of-sale
applications.
When the PARAMETERIZATION FORCED option is enabled, any literal value that appears in a SELECT, INSERT, UPDATE, or DELETE
statement, submitted in any form, is converted to a parameter during
query compilation. The exceptions are literals that appear in the
following query constructs:
INSERT...EXECUTE statements
Statements
inside the bodies of stored procedures, triggers, or user-defined
functions. SQL Server already reuses query plans for these routines.
Prepared statements that have already been parameterized by the client-side application.
Statements inside a T-SQL cursor.
Any statement run in a context where ANSI_PADDING or ANSI_NULLS is set to OFF.
Statements that contain more than 2,097 literals eligible for parameterization.
Statements that reference variables, such as WHERE st.state = @state.
Statements that contain the RECOMPILE or OPTIMIZE FOR query hints.
Statements that contain a COMPUTE clause.
Statements that contain a WHERE CURRENT OF clause.
If an execution plan for a query is cached, you can determine whether the query is parameterized by referencing the sql column of the sys.syscacheobjects
DMV. If a query is parameterized, the names and data types of
parameters are listed in this column before the text of the submitted
SQL (for example, @1 tinyint).
Guidelines for Using Forced Parameterization
Consider the following guidelines when determining whether to enable forced parameterization for a database:
- Forced
parameterization, in effect, changes the literal constants in a query to
parameters when the query is compiled, and thus, the Query Optimizer
might choose suboptimal plans for queries. For example, the Query
Optimizer may be less likely to match the query to an indexed view or an
index on a computed column. It may also choose suboptimal plans for
queries posed on partitioned tables and distributed partitioned views.
Forced parameterization should not be used for environments that rely
heavily on indexed views and indexes on computed columns.
- Enabling the PARAMETERIZATION FORCED option causes all query plans for the database to be flushed from the plan cache.
- Generally, the PARAMETERIZATION FORCED
option should be used only by experienced database administrators after
determining that doing this does not adversely affect performance.
If forced parameterization is
enabled and you want to override this behavior and have simple
parameterization used for a single query and any others that are
syntactically equivalent but differ only in their parameter values, you
can use plan guides and specify PARAMETERIZATION SIMPLE when creating the plan guides. Conversely, rather than enabling PARAMETERIZATION FORCED for an entire database, you can use plan guides and specify the PARAMETERIZATION FORCED
query option only for a specific set of syntactically equivalent
queries that you have determined would benefit from forced
parameterization.
Using the USE PLAN Query Hint
The USE PLAN
query hint in SQL Server 2008 can be used to encourage the Query
Optimizer to use the specified XML query plan for processing the query.
This option provides more control over influencing the execution of a
query than is possible with the other available query hints, such as FORCE ORDER, LOOP JOIN, and KEEP PLAN.
None of these options individually are powerful enough to influence the
Query Optimizer to consistently choose a particular query plan,
especially when the referenced table row counts, statistics, indexes,
and other attributes of the environment change.
The USE PLAN query hint is specified in the OPTION clause, and you provide it with a query plan in XML format. Listing 2 provides an example of the USE PLAN
hint being specified for a merge join for a simple query that consists
of a join between two tables. (Note: For the sake of space, the full XML
plan has been truncated.)
Listing 2. Specifying the USE PLAN Query Option
select st.stor_name, s.ord_date from sales s join stores st on s.stor_id = st.stor_id WHERE st.state = 'NY' OPTION (USE PLAN N' <?xml version="1.0" encoding="utf-16"?> <ShowPlanXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Version="1.1" Build="10.50.1352.12" xmlns="http://schemas.microsoft.com/ sqlserver/2004/07/showplan"> <BatchSequence> <Batch> <Statements> <StmtSimple StatementCompId="1" StatementEstRows="10710.8" StatementId="1" StatementOptmLevel="FULL" StatementSubTreeCost="1.71032" StatementText="select st.stor_name, s.ord_date
 from sales s join stores st on s.stor_id = st.stor_id
 WHERE st.state = ''NY''
" StatementType="SELECT" QueryHash="0x35DE42B697A8BAAF " QueryPlanHash="0x9F4AE50605763B05"> <StatementSetOptions ANSI_NULLS="true" ANSI_PADDING="true" ANSI_WARNINGS="true" ARITHABORT="true" CONCAT_NULL_YIELDS_NULL="true" NUMERIC_ROUNDABORT="false" QUOTED_IDENTIFIER="true" /> <QueryPlan DegreeOfParallelism="1" CachedPlanSize="16" CompileTime="6" CompileCPU="6" CompileMemory="232"> <MissingIndexes> <MissingIndexGroup Impact="13.6636"> <MissingIndex Database="[bigpubs2008]" Schema="[dbo]" Table="[stores]"> <ColumnGroup Usage="EQUALITY"> <Column Name="[state]" ColumnId="5" /> </ColumnGroup> <ColumnGroup Usage="INCLUDE"> <Column Name="[stor_id]" ColumnId="1" /> <Column Name="[stor_name]" ColumnId="2" /> </ColumnGroup> </MissingIndex> </MissingIndexGroup> </MissingIndexes> <RelOp AvgRowSize="39" EstimateCPU="0.363144" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="10710.8" LogicalOp="Inner Join" NodeId="0" Parallel="false" PhysicalOp="Merge Join" EstimatedTotalSubtreeCost="1.71032"> ... <Object Database="[bigpubs2008]" Schema="[dbo]" Table="[sales]" Index="[UPKCL_sales]" Alias="[s]" IndexKind="Clustered" /> </IndexScan> </RelOp> </Merge> </RelOp> </QueryPlan> </StmtSimple> </Statements> </Batch> </BatchSequence> </ShowPlanXML>
|
To obtain an XML-formatted query plan, which you can provide to the USE PLAN query hint, SQL Server 2008 provides the following methods:
Using the SET SHOWPLAN_XML and SET STATISTICS XML session options
Querying the plan column of the sys.dm_exec_query_plan dynamic management view for a cached query plan
Using SQL Server Profiler and capturing either the Showplan XML, Showplan XML Statistics Profile, or Showplan XML For Query Compile event classes
Note
When the XML query plan
contains a character string in single quotation marks (‘), the quotation
marks must be escaped by a second quotation mark before using the plan
with the USE PLAN query hint. For example, a plan that contains WHERE A.varchar = 'This is a string' must be escaped by modifying the code to WHERE A.varchar = ''This is a string''; otherwise, it will generate a syntax error when submitted for execution.
You may choose to use the USE PLAN
hint for queries where the execution plan chosen leads to slow
execution times but for which you know a better plan exists. This
scenario may commonly occur for queries that might have executed well in
an earlier version of SQL Server but that perform poorly under an
upgraded version. Another scenario could be a complex query that
involves multiple tables where the compiled or recompiled query plan
generated is occasionally not optimal, possibly as a result of
out-of-date or missing statistics in any of the underlying tables or
because of complex constructs in the query that cause the Query Optimizer to inaccurately estimate the size of the intermediate query results.
The USE PLAN query hint can be specified only for SELECT and SELECT INTO statements. Also, you can force only query plans that can be produced by the Query Optimizer’s normal optimization strategy.
Because the USE PLAN
option requires that the XML execution plan be hard-coded in the SQL
statement itself, it is not a viable solution for deployed or
third-party applications where it may not be possible or feasible to
modify the queries directly. It’s really useful only as a tool for
troubleshooting poorly running queries. To force query plans to apply
query hints to queries when you cannot or do not want to directly change
the application or SQL code, you might consider using plan guides.