brièvement
[.____] quels facteurs vont-ils dans la sélection de l'indice d'une vue d'une vue indexée?
Pour moi, des vues indexées semblent défier ce que je comprends de la manière dont l'optimiseur choisit les index. J'ai vu cela a demandé auparavant , mais l'OP n'était pas trop bien reçu. Je cherche vraiment des guides, mais je vais concocter un pseudo exemple, puis postez un exemple réel avec beaucoup de DDL, sortie, exemples.
Supposons que j'utilise Enterprise 2008+, comprenez
with(noexpand)
Prenez cet exemple de pseudo: je crée une vue avec 22 jointures, 17 filtres et un poney de cirque qui traverse un tas de tables de 10 millions de rangées. Cette vue est chère (Yep, avec une capitale E) de se matérialiser. Je serai schématiquement et indexez la vue. Puis un SELECT a,b FROM AnIndexedView WHERE theClusterKeyField < 84
. Dans la logique d'optimisation qui m'éludote, les jointures sous-jacentes sont effectuées.
Le résultat:
Alors qu'est-ce qui se passe ici? Je l'ai essayé in Entreprise 2008, 2008-R2 et 2012. Par chaque métrique, je pense que l'utilisation de l'indice de l'avis est considérablement plus efficace. Je n'ai pas de problème de reniflement des paramètres ni de données asymétriques, car il s'agit de l'annonce.
Sauf si vous êtes une touche masochiste, vous n'avez probablement pas besoin de lire cette partie.
la version
oui, entreprise.
Microsoft SQL Server 2012 - 11.0.2100.60 (X64) 10 févr. 2012 19:39:15 Copyright (c) Microsoft Corporation Enterprise Edition (64 bits) sur Windows NT 6.2 (Buildrovish 9200 :) (Hypervisor)
la vue
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
Index en cluster
CREATE UNIQUE CLUSTERED INDEX PK_TimelineMaterialized ON
TimelineMaterialized (EmployeeID, CreateUTC, CultureCode, TimelineID)
Test 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'
résultat = 11 rangées de sortie
Sortie du profileur
[.____] Les 4 lignes supérieures sont sans indice. Les 4 lignes inférieures utilisent l'indice.
Plans d'exécution
[.____] GIST GITUB pour les deux plans d'exécution au format SQLPLAN
Aucun plan d'exécution d'indice - Pourquoi ne pas utiliser l'index en cluster, je vous ai donné M. SQL? C'est Clusterd sur les 3 champs de filtrage. Essayez-le, vous pourriez aimer.
Plan simple lorsque vous utilisez un indice.
Les vues indexées correspondantes sont une opération relativement coûteuse *, l'optimiseur essaie donc d'abord d'autres transformations rapides et faciles. Si ceux-ci produisent un plan bon marché (0,05 unités dans votre cas) l'optimisation se termine tôt. Le pari est que l'optimisation continue consommerait plus de temps qu'il en a sauvegardé. N'oubliez pas que l'objectif principal de l'optimiseur est un plan "assez bon" rapidement.
en utilisant L'index en cluster sur la vue n'est pas coûteux en soi, mais le processus de correspondance d'une arborescence de requête logique à des vues indexées potentielles peut être. Comme je l'ai mentionné dans un commentaire sur l'autre question, la référence de vue dans la requête est développée avant l'optimisation, l'optimiseur ne sait pas que vous avez écrit la requête contre la vue en premier lieu - elle ne voit que l'arbre expansé (comme si la vue avait été intégrée).
"Bon plan suffisant" signifie que l'optimiseur a trouvé un plan décent et s'est arrêté tôt dans une phase d'exploration. "Timeout" signifie qu'il a dépassé le nombre d'étapes d'optimisation qu'il s'est fixé comme un "budget" au début de la phase actuelle.
Le budget est défini sur la base du coût du meilleur plan trouvé lors d'une phase précédente. Avec une telle requête à faible coût (0,05), le nombre de mouvements budgétisés sera assez petit et rapidement épuisé par une transformation régulière compte tenu du nombre de jointures impliquées dans votre requête d'échantillon (il existe de nombreuses façons de réorganiser les jointures intérieures, par exemple) .
Si vous êtes intéressé à en savoir plus sur la raison pour laquelle la correspondance d'une vue indexée coûte cher, et donc laissée pour des étapes ultérieures d'optimisation et/ou uniquement de requêtes plus coûteuses, il existe deux documents de recherche Microsoft sur le sujet ici (PDF) et ici (Citeser).
Un autre facteur pertinent est que la correspondance d'une vue indexée n'est pas disponible en phase d'optimisation 0 (traitement de la transaction).
En plus de lecture:
* et uniquement disponible dans Enterprise Edition (ou équivalent)