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
Profiler-Ausgabe
Die obersten 4 Zeilen enthalten keinen Hinweis. Die unteren 4 Zeilen verwenden den Hinweis.
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.
Einfacher Plan bei Verwendung eines Hinweises.