DATABASE

SQL Server 2008 : Managing Query Performance - Optimizing for Specific Parameter Values

2/15/2011 7:58:02 PM
The OPTIMIZE FOR query hint was introduced in SQL Server 2005 to allow you to specify a value the query optimizer will use when creating an execution plan for parameterized queries. SQL Server 2008 has enhanced this query hint by adding the UNKNOWN option, which instructs the query optimizer to use statistical information when creating the execution plan instead of the supplied value. The OPTIMIZE FOR query hint is useful when different parameter values create different execution plans. If you create a stored procedure, and the execution plan is cached based on infrequently used values, you could suffer from a poorly cached execution plan.

Let's look at a couple of queries where the execution plan changes based on the search value. The query in Listing 1 performs a basic join on the SalesOrderDetail and the SalesOrderHeader tables and limits the results to only orders with a quantity of one.

Example 1. Query That Will Generate an Execution Plan That Uses a Merge Join
USE AdventureWorks2008
GO

SELECT B.CustomerID
FROM Sales.SalesOrderDetail A
JOIN Sales.SalesOrderHeader B
ON A.SalesOrderID = B.SalesOrderID
WHERE A.OrderQty = 1

The query optimizer chooses a merge join for the query in Listing 1 because there are almost 75,000 rows with an order quantity of one. You can view the execution plan for Listing 1 in Figure 1.

Figure 1. Execution plan generated for the query in Listing 16-6

Let's execute the same query with one minor change, as shown in Listing 2. If you look closely, you will see the only difference between the queries in Listing 1 and Listing 2 is that we changed the value in the WHERE clause to limit the results to only include orders with an order quantity of ten.

Example 2. Query That Will Generate an Execution Plan That Uses a Hash Join
USE AdventureWorks2008
GO

SELECT B.CustomerID
FROM Sales.SalesOrderDetail A
JOIN Sales.SalesOrderHeader B
ON A.SalesOrderID = B.SalesOrderID
WHERE A.OrderQty = 10

As you can see in Figure 2, making a simple change in the WHERE clause causes the query optimizer to use a hash match to join the records, since there are only 768 rows with an order quantity of ten.

Figure 2. Execution plan generated for the query in Listing 16-7

Now let's execute the same query using a variable with a value of ten instead of hard coding the value. Let's also optimize the query as if the variable being used contained the number one, as shown in Listing 3.

Example 3. Using the OPTIMIZE FOR Query Hint to Optimize the Execution Plan for a Value of One
USE AdventureWorks2008
GO

DECLARE @ID int =10

SELECT B.CustomerID
FROM Sales.SalesOrderDetail A
JOIN Sales.SalesOrderHeader B
ON A.SalesOrderID = B.SalesOrderID
WHERE A.OrderQty = @ID
OPTION (OPTIMIZE FOR (@ID = 1))

As you can see in Figure 3, the execution plan now contains a merge join instead of the hash join that the query optimizer would have normally chosen for the value of ten.

Figure 3. Execution plan generated for the query in Listing 16-8

Let's execute the query once again using a variable of one, which should cause the query optimizer to choose a merge join. Let's also change the query hint to optimize for UNKNOWN to instruct the query optimizer to use statistical information to create the query plan, as shown in Listing 4.

Example 4. Using the OPTIMIZE FOR query hint to Optimize the Execution Plan for an Unknown Value
USE AdventureWorks2008
GO

DECLARE @ID2 int =1

SELECT B.CustomerID
FROM Sales.SalesOrderDetail A
JOIN Sales.SalesOrderHeader B
ON A.SalesOrderID = B.SalesOrderID
WHERE A.OrderQty = @ID2
OPTION (OPTIMIZE FOR (@ID2 UNKNOWN))

As you can see in Figure 4, the statistical information causes the query optimizer to use a hash join instead of a merge join that the optimizer would have normally chosen for the value of one. It chooses the hash join because, based on the statistical information, you are more likely to pass in a variable that will perform better using the hash join.

Figure 4. Execution plan generated for the query in Listing 16-9

Make sure you know the usage patterns of the application when using the OPTIMIZE FOR query hint. You may need to modify the optimization values from time to time. Optimal parameters today may not be the optimal parameters a year from now.

Other  
  •  SQL Server 2008 : Managing Query Performance - Running the Standard Performance Reports
  •  SQL Server 2008 : Explaining XML - Well-Formed XML
  •  SQL Server 2008 : Explaining XML - XML Schema
  •  SQL Azure : Tuning Techniques (part 5) - Provider Statistics & Application Design
  •  SQL Azure : Tuning Techniques (part 4) - Indexed Views & Stored Procedures
  •  SQL Azure : Tuning Techniques (part 3) - Indexing
  •  SQL Azure : Tuning Techniques (part 2) - Connection Pooling & Execution Plans
  •  SQL Azure : Tuning Techniques (part 1) - Dynamic Management Views
  •  Synching an On-Premises Database with SQL Azure
  •  SQL Server 2008 : Managing Query Performance - Finding Similar Queries
  •  SQL Server 2008 : Correlating Profiler and the Performance Monitor
  •  SQL Server 2008 : Explaining XML - XML Indexes
  •  SQL Server 2008 : Explaining XML - XQuery and XPath
  •  SQL Azure : Managing a Shard (part 2) - Working with Partial Shards
  •  SQL Server 2008 : OPENXML, sp_xml_preparedocument, and sp_xml_removedocument
  •  SQL Server 2008 : Retrieving and Transforming XML Data
  •  SQL Azure: Building a Shard (part 4) - Updating and Deleting Records in the Shard & Adding Records to the Shard
  •  SQL Azure: Building a Shard (part 3) - Reading Using the Shard & Caching
  •  SQL Azure: Building a Shard (part 2) - Managing Database Connections
  •  SQL Azure: Building a Shard (part 1) - Designing the Shard Library Object
  •  
    Most View
    Sony RX1 - The World’s Smallest Full-Frame Camera (Part 2)
    Mobile Application Security : SMS Security - Protocol Attacks (part 1)
    15 Practical Tips For Building A Better PC (Part 1)
    Building Your First Windows Phone 7 Application (part 3) - Writing Your First Windows Phone Code
    Windows Mobile Security - Kernel Architecture
    Change In Technology Services In 2013
    Zyxel WHD6215 Wireless HDMI Kit
    Tracking Results and Measuring Success : Tying SEO to Conversion and ROI
    Expert advice: Printer & Scanner (Part 2) - Samsung ML-2955DW
    Advanced ASP.NET : The Entity Framework (part 3) - Handling Errors & Navigating Relationships
    Top 10
    ADO.NET Programming : Microsoft SQL Server (part 4) - Working with Typed Data Sets
    ADO.NET Programming : Microsoft SQL Server (part 3) - Using Stored Procedures with DataSet Objects
    ADO.NET Programming : Microsoft SQL Server (part 2) - Using SQL Server Stored Procedures
    ADO.NET Programming : Microsoft SQL Server (part 1) - Connecting to SQL Server, Creating Command Objects
    Windows Phone 8 In-Depth Review (Part 6)
    Windows Phone 8 In-Depth Review (Part 5)
    Windows Phone 8 In-Depth Review (Part 4)
    Windows Phone 8 In-Depth Review (Part 3)
    Windows Phone 8 In-Depth Review (Part 2)
    Windows Phone 8 In-Depth Review (Part 1)