I put together a scenario that demonstrates how a query session’s SET options can impact which index is used by the Query Optimizer. In this example, I’ll start off by creating a schema-bound view in the AdventureWorks database:
CREATE VIEW dbo.vw_SalesOrderDetail
WITH SCHEMABINDING
AS
SELECT SalesOrderID, SalesOrderDetailID,
CarrierTrackingNumber, ProductID, LineTotal
FROM Sales.SalesOrderDetail
WHERE LineTotal BETWEEN 35.000 AND 50.000
GO
Next, I’ll create two indexes on the view I just created. The first index is a unique clustered index on the composite key of the underlying base table, and the second index is nonclustered on the CarrierTrackingNumber column:
CREATE UNIQUE CLUSTERED INDEX
idx_vw_SalesOrderDetail_Unique ON
dbo.vw_SalesOrderDetail (SalesOrderID,
SalesOrderDetailID)
GO
CREATE INDEX
idx_vw_SalesOrderDetail_CarrierTrackingNumber ON
dbo.vw_SalesOrderDetail (CarrierTrackingNumber)
GO
Now I’ll show the estimated query execution plan for a query that selects against the base table (on top of which I created the view and associated indexes):
SET SHOWPLAN_ALL ON
GO
SELECT SalesOrderID, SalesOrderDetailID,
CarrierTrackingNumber, ProductID, LineTotal
FROM Sales.SalesOrderDetail
WHERE CarrierTrackingNumber = ‘8E3A-4564-99′ AND
LineTotal BETWEEN 35.000 AND 50.000
The argument column of the 4th row of the SHOWPLAN_ALL recordset reveals an Index Seek against the following object:
OBJECT:([AdventureWorks].[dbo].
[vw_SalesOrderDetail].
[idx_vw_SalesOrderDetail_CarrierTrackingNumber]), SEEK:([AdventureWorks].[dbo].
[vw_SalesOrderDetail].[CarrierTrackingNumber]=N’8E3A-4564-99′) ORDERED FORWARD
Even though I was just querying the base table - the query optimizer was able to figure out that the index on the CarrierTrackingNumber column for the indexed view would be a good choice for the query.
Now I'll show the estimated query again - this time designating a different SET option from my session default:
SET SHOWPLAN_ALL ON
GO
SET QUOTED_IDENTIFIER OFF
GO
SELECT SalesOrderID, SalesOrderDetailID,
CarrierTrackingNumber, ProductID, LineTotal
FROM Sales.SalesOrderDetail
WHERE CarrierTrackingNumber = ‘8E3A-4564-99′ AND
LineTotal BETWEEN 35.000 AND 50.000
Looking in the SHOWPLAN_ALL result set - the Index Seek we saw before is missing - replaced by a Clustered Index Scan against the base table:
OBJECT:([AdventureWorks].[Sales].
[SalesOrderDetail].
[PK_SalesOrderDetail_SalesOrderID_SalesOrderDetailID])
What happenend? Index views require that the QUOTED_IDENTIFIER be set ON when the view is created (as well as some other SET options documented in BOL). In order for the Query Optimizer to use the index on the view, these SET options need to match. If they don’t - the Query Optimizer doesn’t consider the index for the query execution plan.
Cross-posted from www.JoeSack.com.