Dlaczego wskazówka READPAST powoduje ignorowanie widoków indeksowanych?

10

Badam za pomocą READPASTpodpowiedzi, aby zmniejszyć blokowanie zasobów w podsystemie finansowym naszej aplikacji.

Wydawało się, że to dobra droga, ponieważ zapisy transakcji finansowych są tylko dodawane, nigdy nie aktualizowane ani usuwane. Jedynymi wierszami, które można kiedykolwiek pominąć, są nowe wiersze wstawione do transakcji; faktycznie nie istnieją w świecie zewnętrznym, dopóki transakcja nie zostanie zatwierdzona.

Zauważyłem jednak gorszą wydajność zapytań korzystających z widoków indeksowanych, o których wspomniałem READPAST. Porównując plany zapytań, wygląda to tak, jak ze wskazówką, optymalizator zapytań decyduje się nie używać widoku indeksowanego, a zamiast tego powraca do traktowania go jak zwykłego widoku.

Nie jestem pewien, dlaczego tak byłoby; Wyobrażam sobie, że indeksowane widoki są jak każdy inny indeks w tym, że klucze mogą być blokowane podczas operacji, a dodawanie READPASTdziałałoby podobnie.

SELECT TOP 1 isa.InvoiceId
FROM Financial_InvoiceSummaryAmounts isa WITH (READPAST)
WHERE isa.TotalOwedAmount = 0.0

wprowadź opis zdjęcia tutaj

SELECT TOP 1 isa.InvoiceId
FROM Financial_InvoiceSummaryAmounts isa
WHERE isa.TotalOwedAmount = 0.0

wprowadź opis zdjęcia tutaj

NOEXPANDWydaje się, że dodanie podpowiedzi również działa, ale interesuje mnie więcej informacji na temat tego, dlaczego READPASToptymalizator zapytań dokonał tego wyboru w pierwszej kolejności (w ramach pełnej odpowiedzi).

Mars
źródło

Odpowiedzi:

7

Ponowne użycie przykładowej tabeli i widoku indeksowanego z mojego artykułu Kolejny powód, aby korzystać ze NOEXPANDwskazówek w wersji Enterprise Edition :

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;

Repro

To zapytanie pasuje do widoku indeksowanego (aczkolwiek z redundantnym agregatem):

SELECT DISTINCT
    VT.col1 
FROM dbo.VT AS VT;

Dopasowany widok indeksowany

Dodanie READPASTpodpowiedzi powoduje dostęp do tabeli podstawowej:

SELECT DISTINCT
    VT.col1 
FROM dbo.VT AS VT 
    WITH (READPAST);

Widok indeksowany nie jest dopasowany

Wyjaśnienie

READPASTWskazówka jest semantyczny wpływających. Optymalizator opiera się przepisywaniu zapytań w taki sposób, że zmieniają się wyniki. Ilustrować:

Następujące zapytanie wykonuje się bez problemów:

SELECT DISTINCT
    VT.col1 
FROM dbo.VT AS VT 
    WITH (READPAST);

Jednak:

SELECT DISTINCT
    VT.col1 
FROM dbo.VT AS VT 
    WITH (READPAST)
OPTION 
    (TABLE HINT (VT, FORCESCAN));

Powoduje błąd:

Msg 8722, poziom 16, stan 1, wiersz 42
Nie można wykonać zapytania.
Semantyczna wskazówka „readpast” pojawia się w klauzuli „WITH” obiektu „VT”
ale nie w odpowiedniej klauzuli „WSKAZÓWKA TABELI”.
Zmień klauzulę OPCJA (WSKAZÓWKI TABELI ...), aby semantyczny wpływający na podpowiedzi
dopasuj klauzulę WITH.

Gdy odwołujesz się do widoku indeksowanego bez NOEXPANDpodpowiedzi, widok jest rozszerzany (przed rozpoczęciem kompilacji i optymalizacji) w celu odniesienia do obiektów leżących u jego podstaw. Na późniejszym etapie optymalizator może rozważyć dopasowanie drzewa zapytań z powrotem do widoku indeksowanego, w całości lub w części.

Gdy READPASTjest używana bez NOEXPAND, podpowiedź propaguje się do tabeli podstawowej, uniemożliwiając dopasowanie widoku (inna semantyka).

Dzięki NOEXPANDpodpowiedź dotyczy bezpośrednio widoku, więc nie ma problemu.

Paul White 9
źródło