Welche Faktoren fließen in die Auswahl des Clustered Index einer indizierten Ansicht ein?

19

Kurz gesagt:
Welche Faktoren beeinflussen die Auswahl des Index einer indizierten Ansicht durch das Abfrageoptimierungsprogramm?

Für mich scheinen indizierte Ansichten dem zu trotzen, was ich über das Auswählen von Indizes durch den Optimierer verstehe. Ich habe dies schon einmal gefragt gesehen , aber das OP wurde nicht allzu gut aufgenommen. Ich bin wirklich auf der Suche nach Wegweisern , aber ich werde ein Pseudobeispiel erstellen und dann ein echtes Beispiel mit vielen DDL-, Ausgabe- und Beispieldateien veröffentlichen.

Angenommen, ich verwende Enterprise 2008+, verstehen Sie with(noexpand)

Pseudo-Beispiel

Nehmen Sie dieses Pseudobeispiel: Ich erstelle eine Ansicht mit 22 Verknüpfungen, 17 Filtern und einem Zirkuspony, das 10 Millionen Zeilentabellen überquert. Diese Ansicht ist teuer (yep, mit einem Kapital E) zu materialisieren. Ich werde die Ansicht SCHEMABINDEN und indizieren. Dann a SELECT a,b FROM AnIndexedView WHERE theClusterKeyField < 84. In der Optimiererlogik, die sich mir entzieht, werden die zugrunde liegenden Verknüpfungen ausgeführt.

Das Ergebnis:

  • Kein Hinweis: 4825 Lesevorgänge für 720 Zeilen, 47 CPU über 76 ms und geschätzte Teilbaumkosten von 0,30523.
  • Mit Hinweis: 17 Lesevorgänge, 720 Zeilen, 15 CPU über 4 ms und geschätzten Teilbaumkosten von 0,007253

Also, was ist hier los? Ich habe es in Enterprise 2008, 2008-R2 und 2012 ausprobiert . Durch jede Metrik, die ich mir vorstellen kann, ist die Verwendung des Index der Ansicht erheblich effizienter. Ich habe kein Parameter-Sniffing-Problem oder verzerrte Daten, da dies ad hock ist.

Ein echtes (langes) Beispiel

Wenn Sie kein Masochist sind, brauchen oder wollen Sie diesen Teil wahrscheinlich nicht lesen.

Die Version
Ja, Unternehmen.

Microsoft SQL Server 2012 - 11.0.2100.60 (X64) 10. Februar 2012, 19:39:15 Uhr Copyright (c) Microsoft Corporation Enterprise Edition (64-Bit) unter Windows NT 6.2 (Build 9200:) (Hypervisor)

Die Aussicht

CREATE VIEW dbo.TimelineMaterialized    WITH SCHEMABINDING
AS
SELECT  TM.TimelineID,
        TM.TimelineTypeID,
        TM.EmployeeID,
        TM.CreateUTC,
        CUL.CultureCode,
        CASE 
           WHEN TM.CustomerMessageID    > 0 THEN TM.CustomerMessageID
           WHEN TM.CustomerSessionID    > 0 THEN TM.CustomerSessionID
           WHEN TM.NewItemTagID         > 0 THEN TM.NewItemTagID
           WHEN TM.OutfitID             > 0 THEN TM.OutfitID
           WHEN TM.ProductTransactionID > 0 THEN TM.ProductTransactionID
           ELSE 0 END  As HrefId,
        CASE 
          WHEN TM.CustomerMessageID    > 0 THEN IsNull(C.Name, 'N/A')   
          WHEN TM.CustomerSessionID    > 0 THEN IsNull(C.Name, 'N/A')
          WHEN TM.NewItemTagID         > 0 THEN IsNull(NI.Title, 'N/A')
          WHEN TM.OutfitID             > 0 THEN IsNull(O.Name, 'N/A')
          WHEN TM.ProductTransactionID > 0 THEN IsNull(PT_PL.NameLocalized, 'N/A')
                 END as HrefText

FROM       dbo.Timeline TM
INNER JOIN dbo.CustomerSession    CS    ON TM.CustomerSessionID    = CS.CustomerSessionID
INNER JOIN dbo.CustomerMessage    CM    ON TM.CustomerMessageID    = CM.CustomerMessageID
INNER JOIN dbo.Outfit             O     ON PO.OutfitID             = O.OutfitID
INNER JOIN dbo.ProductTransaction PT    ON TM.ProductTransactionID = PT.ProductTransactionID
INNER JOIN dbo.Product            PT_P  ON PT.ProductID            = PT_P.ProductID
INNER JOIN dbo.ProductLang        PT_PL ON PT_P.ProductID          = PT_PL.ProductID
INNER JOIN dbo.Culture            CUL   ON PT_PL.CultureID         = CUL.CultureID
INNER JOIN dbo.NewsItemTag        NIT   ON TM.NewsItemTagID        = NIT.NewsItemTagID
INNER JOIN dbo.NewsItem           NI    ON NIT.NewsItemID          = NI.NewsItemID
INNER JOIN dbo.Customer           C     ON  C.CustomerID = CASE 
                                             WHEN TM.TimelineTypeID = 1 THEN CM.CustomerID 
                                             WHEN TM.TimelineTypeID = 5 THEN CS.CustomerID
                                             ELSE 0 END

WHERE        CUL.IsActive = 1

Clustered Index

CREATE UNIQUE CLUSTERED INDEX PK_TimelineMaterialized  ON 
                   TimelineMaterialized (EmployeeID, CreateUTC, CultureCode, TimelineID)

Testen Sie SQL

-- NO HINT - - -  - - -  - - -  - - -  - - - 
SELECT  *                 --yes yes, star is bad ...just a test example
FROM    TimelineMaterialized TM 
WHERE 
            TM.EmployeeID   = 2
        AND TM.CultureCode  = 'en-US'
        AND TM.CreateUTC    > '9/10/2012'
        AND TM.CreateUTC    < '9/11/2012'

-- WITH HINT - - -  - - -  - - -  - - -  - - - 
SELECT  *               
FROM    TimelineMaterialized TM with(noexpand)
WHERE 
            TM.EmployeeID   = 2
        AND TM.CultureCode  = 'en-US'
        AND TM.CreateUTC    > '9/10/2012'
        AND TM.CreateUTC    < '9/11/2012'

Ergebnis = 11 Ausgabezeilen

11 Ausgabezeilen - für beide Abfragen gleich

Profiler-Ausgabe
Die obersten 4 Zeilen enthalten keinen Hinweis. Die unteren 4 Zeilen verwenden den Hinweis.

Profiler

Ausführungspläne
GitHub Gist für beide Ausführungspläne im SQLPlan-Format

Kein Hinweis-Ausführungsplan - warum nicht den Clustered-Index verwenden, den ich Ihnen Mr. SQL gegeben habe? Es ist Clusterd auf den 3 Filterfeldern. Probieren Sie es aus, es könnte Ihnen gefallen.
Kein Tipp - riesiger Ausführungsplan

Einfacher Plan bei Verwendung eines Hinweises.

Verwenden von Hinweis - Einfacher Ausführungsplan

EBarr
quelle
Diskussion zum Chatten verschoben
Paul White sagt GoFundMonica

Antworten:

26

Das Abgleichen indizierter Ansichten ist ein relativ teurer Vorgang *, sodass das Optimierungsprogramm zuerst andere schnelle und einfache Transformationen durchführt. Wenn sich daraus ein billiger Plan ergibt (in Ihrem Fall 0,05 Einheiten), endet die Optimierung vorzeitig. Die Wette ist, dass die fortgesetzte Optimierung mehr Zeit verbraucht als gespart. Denken Sie daran, dass das Hauptziel des Optimierers darin besteht, schnell einen Plan zu erstellen, der „gut genug“ ist.

Die Verwendung des Clustered-Index für die Ansicht ist an sich nicht teuer, aber der Prozess des Abgleichs eines logischen Abfragebaums mit potenziellen indizierten Ansichten kann sehr aufwändig sein. Wie ich in einem Kommentar zu der anderen Frage erwähnt habe, wird die Ansichtsreferenz in der Abfrage vor der Optimierung erweitert, sodass der Optimierer nicht weiß, dass Sie die Abfrage an erster Stelle für die Ansicht geschrieben haben - er sieht nur den erweiterten Baum (als ob die Aussicht war eingezeichnet).

"Good Enough Plan" bedeutet, dass der Optimierer einen angemessenen Plan gefunden und in einer Explorationsphase vorzeitig abgebrochen hat. "TimeOut" bedeutet, dass die Anzahl der Optimierungsschritte überschritten wurde, die zu Beginn der aktuellen Phase als "Budget" festgelegt wurden.

Das Budget wird basierend auf den Kosten des besten Plans festgelegt, der in einer vorherigen Phase ermittelt wurde. Bei einer solchen kostengünstigen Abfrage (0,05) ist die Anzahl der geplanten Verschiebungen relativ gering und wird aufgrund der Anzahl der Verknüpfungen, die in Ihrer Beispielabfrage enthalten sind, durch regelmäßige Transformation schnell erschöpft (es gibt beispielsweise viele Möglichkeiten, innere Verknüpfungen neu anzuordnen). .

Wenn Sie mehr darüber erfahren möchten, warum der Abgleich von indizierten Ansichten teuer ist und daher für spätere Optimierungsphasen und / oder nur für kostspieligere Abfragen in Betracht gezogen wird, finden Sie hier (pdf) und hier (citeseer ) zwei Microsoft Research Papers zum Thema ).

Ein weiterer relevanter Faktor ist, dass in der Optimierungsphase 0 (Transaktionsverarbeitung) kein indizierter Sichtabgleich verfügbar ist.

Weitere Lektüre:

Indizierte Ansichten und Statistiken

* und nur in Enterprise Edition (oder gleichwertig) verfügbar

Paul White sagt GoFundMonica
quelle