I am investigating using the READPAST
hint to reduce resource locking in our application's financial subsystem.
It seemed like a good way to go because financial transaction records are only ever added, never updated or deleted. The only rows that would ever be skipped are brand new rows inserted inside of a transaction; they effectively don't exist to the outside world until the transaction is committed.
However, I noticed worse performance on queries that utilize indexed views that I had put the READPAST
hint on. Comparing the query plans, it looks like with the hint, the query optimizer chooses to not use the indexed view and instead falls back to treating it like a regular view.
I'm not sure why that would be; I imagine indexed views to be like any other index in that keys can be locked during operations and adding READPAST
would work similarly.
SELECT TOP 1 isa.InvoiceId
FROM Financial_InvoiceSummaryAmounts isa WITH (READPAST)
WHERE isa.TotalOwedAmount = 0.0
SELECT TOP 1 isa.InvoiceId
FROM Financial_InvoiceSummaryAmounts isa
WHERE isa.TotalOwedAmount = 0.0
Adding a NOEXPAND
hint as well does seem to work, but I am interested in learning more about possibly why READPAST
caused the query optimizer to make that choice in the first place (as part of a full answer).
Best Answer
Reusing the example table and indexed view from my article Another Reason to Use
NOEXPAND
hints in Enterprise Edition:Repro
This query matches the indexed view (albeit with a redundant aggregate):
Adding a
READPAST
hint results in accessing the base table:Explanation
The
READPAST
hint is semantic-affecting. The optimizer resists rewriting queries such that the results change. To illustrate:The following query executes without problems:
However:
Produces the error:
When you reference the indexed view without the
NOEXPAND
hint, the view is expanded (before compilation and optimization begins) to reference the underlying objects instead. Later in the process, the optimizer may consider matching the query tree back to an indexed view, in whole or in part.When
READPAST
is used withoutNOEXPAND
, the hint propagates to the base table, preventing view matching (different semantics).With
NOEXPAND
, the hint applies to the view directly, so there is no problem.