为什么 READPAST 提示会导致索引视图被忽略?

Mar*_*ars 10 performance sql-server hints materialized-view query-performance

我正在研究使用READPAST提示来减少我们应用程序财务子系统中的资源锁定。

这似乎是一个不错的方法,因为金融交易记录只会被添加,不会被更新或删除。唯一会被跳过的行是插入事务中的全新行;在事务提交之前,它们实际上不存在于外部世界。

但是,我注意到使用我已READPAST提示的索引视图的查询性能较差。比较查询计划,通过提示,查询优化器选择不使用索引视图,而是退回到将其视为常规视图。

我不确定为什么会这样;我想索引视图就像任何其他索引一样,因为键可以在操作期间被锁定,并且添加的READPAST工作方式类似。

SELECT TOP 1 isa.InvoiceId
FROM Financial_InvoiceSummaryAmounts isa WITH (READPAST)
WHERE isa.TotalOwedAmount = 0.0
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

SELECT TOP 1 isa.InvoiceId
FROM Financial_InvoiceSummaryAmounts isa
WHERE isa.TotalOwedAmount = 0.0
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

添加NOEXPAND提示似乎也有效,但我有兴趣了解更多关于可能READPAST导致查询优化器首先做出该选择的原因(作为完整答案的一部分)。

Pau*_*ite 7

重用我的文章中的示例表和索引视图在企业版中使用NOEXPAND提示的另一个原因

CREATE TABLE dbo.T
(
    col1 integer NOT NULL
);
GO
INSERT dbo.T WITH (TABLOCKX)
    (col1)
SELECT 
    SV.number
FROM master.dbo.spt_values AS SV
WHERE 
    SV.type = N'P';
GO
CREATE VIEW dbo.VT
WITH SCHEMABINDING
AS
SELECT T.col1 
FROM dbo.T AS T;
Run Code Online (Sandbox Code Playgroud)

再现

此查询与索引视图匹配(尽管具有冗余聚合):

SELECT DISTINCT
    VT.col1 
FROM dbo.VT AS VT;
Run Code Online (Sandbox Code Playgroud)

索引视图匹配

添加READPAST提示会导致访问基表:

SELECT DISTINCT
    VT.col1 
FROM dbo.VT AS VT 
    WITH (READPAST);
Run Code Online (Sandbox Code Playgroud)

索引视图不匹配

解释

READPAST提示是语义的影响。优化器拒绝重写查询,从而改变结果。为了显示:

以下查询执行没有问题:

SELECT DISTINCT
    VT.col1 
FROM dbo.VT AS VT 
    WITH (READPAST);
Run Code Online (Sandbox Code Playgroud)

然而:

SELECT DISTINCT
    VT.col1 
FROM dbo.VT AS VT 
    WITH (READPAST)
OPTION 
    (TABLE HINT (VT, FORCESCAN));
Run Code Online (Sandbox Code Playgroud)

产生错误:

Msg 8722, Level 16, State 1, Line 42
无法执行查询。
语义影响提示“readpast”出现在对象“VT”的“WITH”子句中
但不在相应的“TABLE HINT”子句中。
更改 OPTION (TABLE HINTS...) 子句,使语义影响提示
匹配 WITH 子句。

当您在没有NOEXPAND提示的情况下引用索引视图时,视图会扩展(在编译和优化开始之前)以引用底层对象。在该过程的后期,优化器可能会考虑将查询树全部或部分地匹配回索引视图。

READPAST不使用时NOEXPAND,提示传播到基表,防止视图匹配(不同的语义)。

使用NOEXPAND,提示直接应用于视图,所以没有问题。