En essayant d'appliquer le contenu de cette question ci-dessous à ma propre situation, je suis un peu confus quant à la façon dont je pourrais me débarrasser de l'opérateur Hash Match (Inner Join) si possible.
J'ai remarqué le coût de 10% et je me demandais si je pouvais le réduire. Voir le plan de requête ci-dessous.
Ce travail provient d'une requête que j'ai dû régler aujourd'hui:
SELECT c.AccountCode, MIN(d.CustomerSID)
FROM Stage.Customer c
INNER JOIN Dimensions.Customer d ON c.Email = d.Email
OR (
c.HomePostCode = d.HomePostCode
AND c.StrSurname = d.strSurname
)
GROUP BY c.AccountCode
et après avoir ajouté ces index:
---------------------------------------------------------------------
-- Create the indexes
---------------------------------------------------------------------
CREATE NONCLUSTERED INDEX IDX_Stage_Customer_HOME_SURNAME_INCL
ON Stage.Customer(HomePostCode ,strSurname)
INCLUDE (AccountCode)
--WHERE HASEMAIL = 0
--WITH (ONLINE=ON, DROP_EXISTING = ON)
go
CREATE NONCLUSTERED INDEX IDX_Dimensions_Customer_HOME_SURNAME_INCL
ON Dimensions.Customer(HomePostCode ,strSurname)
INCLUDE (AccountCode,CustomerSID)
--WHERE HASEMAIL = 0
--WITH (ONLINE=ON, DROP_EXISTING = ON)
go
CREATE NONCLUSTERED INDEX IDX_Stage_Customer_EMAIL_INCL
ON Stage.Customer(EMAIL)
INCLUDE (AccountCode)
--WHERE HASEMAIL = 1
--WITH (ONLINE=ON, DROP_EXISTING = ON)
go
CREATE NONCLUSTERED INDEX IDX_Dimensions_Customer_EMAIL_INCL
ON Dimensions.Customer(EMAIL)
INCLUDE (AccountCode,CustomerSID)
--WHERE HASEMAIL = 1
--WITH (ONLINE=ON, DROP_EXISTING = ON)
go
c'est la nouvelle requête:
----------------------------------------------------------------------------
-- new query
----------------------------------------------------------------------------
SELECT *
FROM (
SELECT AccountCode
,RO=ROW_NUMBER () OVER (PARTITION BY AccountCode ORDER BY CustomerSID)
--,CustomerSID=MIN(CustomerSID) OVER (PARTITION BY AccountCode ORDER BY AccountCode)
,CustomerSID
FROM (
SELECT c.AccountCode, D.CustomerSID
FROM Stage.Customer c
INNER JOIN Dimensions.Customer d ON c.Email = d.Email
UNION ALL
SELECT c.AccountCode, D.CustomerSID
FROM Stage.Customer c
INNER JOIN Dimensions.Customer d ON c.HomePostCode = d.HomePostCode
AND c.StrSurname = d.strSurname
) RADHE
) R1
WHERE RO = 1
Cela a réduit le temps d'exécution des requêtes de 8 minutes à 1 seconde.
Tout le monde est content, mais j'aimerais quand même savoir si je pourrais en faire plus, c'est-à-dire en supprimant en quelque sorte l'opérateur de correspondance de hachage.
Pourquoi est-il là en premier lieu, je fais correspondre tous les champs, pourquoi le hachage?
les liens suivants fourniront une bonne source de connaissances concernant les plans d'exécution.
De Notions de base du plan d'exécution - Confusion de correspondance de hachage J'ai trouvé:
De http://sqlinthewild.co.za/index.php/2007/12/30/execution-plan-operations-joins/
"La jointure de hachage est l'une des opérations de jointure les plus coûteuses, car elle nécessite la création d'une table de hachage pour effectuer la jointure. Cela dit, c'est la jointure qui convient le mieux pour les entrées volumineuses non triées. Elle est la plus gourmande en mémoire de tous les des jointures
La jointure de hachage lit d'abord l'une des entrées et hache la colonne de jointure et place le hachage résultant et les valeurs de colonne dans une table de hachage construite en mémoire. Il lit ensuite toutes les lignes de la deuxième entrée, les hache et vérifie les lignes dans le compartiment de hachage résultant pour les lignes de jointure. "
qui renvoie à ce post:
http://blogs.msdn.com/b/craigfr/archive/2006/08/10/687630.aspx
Pouvez-vous expliquer ce plan d'exécution? fournit de bonnes informations sur le plan d'exécution avec, non spécifique à la correspondance de hachage mais pertinent.
Les analyses constantes sont un moyen pour SQL Server de créer un compartiment dans lequel il va placer quelque chose plus tard dans le plan d'exécution. J'ai posté un ne explication plus approfondie ici . Pour comprendre à quoi sert le balayage constant, vous devez approfondir le plan. Dans ce cas, ce sont les opérateurs de calcul scalaire qui sont utilisés pour remplir l'espace créé par l'analyse constante.
Les opérateurs de calcul scalaire sont chargés avec NULL et la valeur 1045876, ils seront donc clairement utilisés avec la jointure en boucle dans le but de filtrer les données.
La partie vraiment cool est que ce plan est Trivial. Cela signifie qu'il a subi un processus d'optimisation minimal. Toutes les opérations mènent à l'intervalle de fusion. Ceci est utilisé pour créer un ensemble minimal d'opérateurs de comparaison pour une recherche d'index ( détails à ce sujet ici ).
Dans cette question: Puis-je obtenir SSMS pour me montrer les coûts de requête réels dans le volet Plan d'exécution? Je corrige des problèmes de performances sur une procédure stockée à plusieurs états dans SQL Server. Je veux savoir sur quelle (s) partie (s) je dois passer du temps.
Je comprends de Comment lire le coût de la requête, et est-ce toujours un pourcentage? que même lorsque SSMS est invité à inclure le plan d'exécution réel, les chiffres du "coût de la requête (par rapport au lot)" sont toujours basé sur des estimations de coûts, qui peuvent être très éloignées des chiffres réels
Mesurer les performances des requêtes: "Coût des requêtes du plan d'exécution" vs "Temps pris" donne de bonnes informations pour savoir quand vous devez comparer les performances de 2 requêtes différentes.
Dans Lecture d'un plan d'exécution SQL Server vous pouvez trouver d'excellents conseils pour lire le plan d'exécution.
D'autres questions/réponses que j'ai vraiment aimées parce qu'elles sont pertinentes à ce sujet, et pour ma référence personnelle, je voudrais citer:
Comment optimiser la requête T-SQL à l'aide du plan d'exécution
SQL peut-il générer un bon plan pour cette procédure?
Les plans d'exécution diffèrent pour la même instruction SQL