Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Différence de performances entre la jointure gauche et la jointure interne

Il y a au moins un cas où LEFT [OUTER] JOIN est une meilleure option que [INNER] JOIN . Je parle d'obtenir les mêmes résultats en utilisant OUTER au lieu de INNER .

Exemple (j'utilise base de données AdventureWorks 2008 ):

-- Some metadata infos
SELECT  fk.is_not_trusted,  fk.name
FROM    sys.foreign_keys fk
WHERE   fk.parent_object_id=object_id('Sales.SalesOrderDetail');
GO

CREATE VIEW View1
AS 
SELECT  h.OrderDate, d.SalesOrderDetailID, o.ModifiedDate
FROM    Sales.SalesOrderDetail d
INNER JOIN Sales.SalesOrderHeader h ON d.SalesOrderID = h.SalesOrderID
INNER JOIN Sales.SpecialOfferProduct o ON d.SpecialOfferID=o.SpecialOfferID AND d.ProductID=o.ProductID;
GO

CREATE VIEW View2
AS
SELECT  h.OrderDate, d.SalesOrderDetailID, o.ModifiedDate
FROM    Sales.SalesOrderDetail d
INNER JOIN Sales.SalesOrderHeader h ON d.SalesOrderID = h.SalesOrderID
LEFT JOIN Sales.SpecialOfferProduct o ON d.SpecialOfferID=o.SpecialOfferID AND d.ProductID=o.ProductID;
GO

SELECT  SalesOrderDetailID
FROM    View1;

SELECT  SalesOrderDetailID
FROM    View2;

Résultats pour la première requête :

is_not_trusted name
-------------- ---------------------------------------------------------------
0              FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID
0              FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID

Plans d'exécution pour les deux dernières requêtes :

Remarque 1/Vue 1 : Si nous regardons le plan d'exécution pour SELECT SalesOrderDetailID FROM View1 nous voyons un Élimination FK car le FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID La contrainte est approuvée et elle a une seule colonne. Mais, le serveur est forcé (à cause de INNER JOIN Sales.SpecialOfferProduct ) pour lire les données de la troisième table (SpecialOfferProduct) même le SELECT/WHERE clauses ne contient aucune colonne de cette table et la contrainte FK (FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID) est (également) approuvée. Cela se produit parce que ce dernier FK est multicolonne.

Remarque 2/Vue 2 : Et si nous voulons supprimer la lecture (Scan /Seek ) sur le Sales.SpecialOfferProduct ? Ce deuxième FK est multicolonne et dans de tels cas, SQL Server ne peut pas éliminer le FK (voir le billet de blog précédent de Conor Cunnigham). Dans ce cas, nous devons remplacer le INNER JOIN Sales.SpecialOfferProduct avec LEFT OUTER JOIN Sales.SpecialOfferProduct afin d'obtenir l'élimination FK. Les deux SpecialOfferID et ProductID les colonnes sont NOT NULL et nous avons un FK de confiance faisant référence à SpecialOfferProduct tableau.