Warum bewirkt der READPAST-Hinweis, dass indizierte Ansichten ignoriert werden?

10

Ich untersuche anhand des READPASTHinweises, die Ressourcensperrung im Finanzsubsystem unserer Anwendung zu verringern.

Es schien ein guter Weg zu sein, da Finanztransaktionsdatensätze immer nur hinzugefügt, nie aktualisiert oder gelöscht werden. Die einzigen Zeilen, die jemals übersprungen würden, sind brandneue Zeilen, die in eine Transaktion eingefügt werden. Sie existieren praktisch nicht nach außen, bis die Transaktion festgeschrieben ist.

Bei Abfragen mit indizierten Ansichten, auf die ich den READPASTHinweis gesetzt hatte, bemerkte ich jedoch eine schlechtere Leistung . Beim Vergleich der Abfragepläne sieht es so aus, als würde der Abfrageoptimierer die indizierte Ansicht nicht verwenden und stattdessen darauf zurückgreifen, sie wie eine normale Ansicht zu behandeln.

Ich bin mir nicht sicher, warum das so ist. Ich stelle mir indizierte Ansichten wie jeden anderen Index vor, bei dem Schlüssel während des Betriebs gesperrt werden können und das Hinzufügen READPASTähnlich funktionieren würde.

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

Geben Sie hier die Bildbeschreibung ein

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

Geben Sie hier die Bildbeschreibung ein

Das Hinzufügen eines NOEXPANDHinweises scheint ebenfalls zu funktionieren, aber ich bin daran interessiert, mehr darüber zu erfahren, warum READPASTdas Abfrageoptimierungsprogramm diese Auswahl überhaupt getroffen hat (als Teil einer vollständigen Antwort).

Mars
quelle

Antworten:

7

Wiederverwenden der Beispieltabelle und der indizierten Ansicht aus meinem Artikel Ein weiterer Grund für die Verwendung von NOEXPANDHinweisen in 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

Diese Abfrage entspricht der indizierten Ansicht (allerdings mit einem redundanten Aggregat):

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

Indizierte Ansicht übereinstimmt

Das Hinzufügen eines READPASTHinweises führt zum Zugriff auf die Basistabelle:

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

Indizierte Ansicht stimmt nicht überein

Erläuterung

Der READPASTHinweis wirkt sich semantisch aus. Das Optimierungsprogramm widersetzt sich dem Umschreiben von Abfragen, sodass sich die Ergebnisse ändern. Um zu veranschaulichen:

Die folgende Abfrage wird ohne Probleme ausgeführt:

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

Jedoch:

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

Erzeugt den Fehler:

Nachricht 8722, Ebene 16, Status 1, Zeile 42
Abfrage kann nicht ausgeführt werden.
Der semantisch beeinflussende Hinweis 'readpast' erscheint in der 'WITH'-Klausel des Objekts' VT '.
aber nicht in der entsprechenden 'TABLE HINT'-Klausel.
Ändern Sie die OPTION-Klausel (TABLE HINTS ...) so, dass die semantische Beeinflussung Hinweise enthält
stimmen mit der WITH-Klausel überein.

Wenn Sie ohne Hinweis auf die indizierte Ansicht verweisen NOEXPAND, wird die Ansicht erweitert (bevor mit der Kompilierung und Optimierung begonnen wird), um stattdessen auf die zugrunde liegenden Objekte zu verweisen. Später im Prozess kann das Optimierungsprogramm in Betracht ziehen, den Abfragebaum ganz oder teilweise wieder mit einer indizierten Ansicht abzugleichen.

Wenn READPASTohne verwendet wird NOEXPAND, der Hinweis ausbreitet zu der Basistabelle, verhindert Ansicht Anpassung (unterschiedliche Semantik).

Mit NOEXPANDgilt der Hinweis direkt für die Ansicht, sodass kein Problem besteht.

Paul White 9
quelle