Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Differenza di prestazioni tra left join e inner join

C'è almeno un caso in cui LEFT [OUTER] JOIN è un'opzione migliore di [INNER] JOIN . Parlo di ottenere gli stessi risultati usando OUTER invece di INNER .

Esempio (sto usando database 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;

Risultati per la prima query:

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

Piani di esecuzione per le ultime due query:

Nota 1 / Vista 1: Se esaminiamo il piano di esecuzione per SELECT SalesOrderDetailID FROM View1 vediamo un Eliminazione FK perché FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID vincolo è attendibile e ha una singola colonna. Ma il server è forzato (a causa di INNER JOIN Sales.SpecialOfferProduct ) per leggere i dati della terza tabella (SpecialOfferProduct) anche il SELECT/WHERE clausole non contiene colonne di questa tabella e il vincolo FK (FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID) è (anche) attendibile. Questo accade perché quest'ultimo FK è multicolonna.

Nota 2 / Vista 2: E se volessimo rimuovere la lettura (Scan /Seek ) sul Sales.SpecialOfferProduct ? Questo secondo FK è multicolonna e per tali casi SQL Server non può eliminare l'FK (vedi precedente post sul blog di Conor Cunnigham). In questo caso dobbiamo sostituire INNER JOIN Sales.SpecialOfferProduct con LEFT OUTER JOIN Sales.SpecialOfferProduct per ottenere l'eliminazione dall'FK. Entrambi SpecialOfferID e ProductID le colonne sono NOT NULL e abbiamo un FK affidabile che fa riferimento a SpecialOfferProduct tabella.