Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Leistungsunterschied zwischen Left Join und Inner Join

Es gibt mindestens einen Fall, in dem LEFT [OUTER] JOIN ist eine bessere Option als [INNER] JOIN . Ich spreche davon, dieselben Ergebnisse mit OUTER zu erhalten statt INNER .

Beispiel (Ich verwende AdventureWorks 2008-Datenbank ):

-- 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;

Ergebnisse für die erste Abfrage:

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

Ausführungspläne für die letzten beiden Abfragen:

Anmerkung 1 / Ansicht 1: Betrachten wir den Ausführungsplan für SELECT SalesOrderDetailID FROM View1 wir sehen einen FK-Eliminierung weil die FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID Einschränkung ist vertrauenswürdig und hat eine einzelne Spalte. Aber der Server wird gezwungen (wegen INNER JOIN Sales.SpecialOfferProduct). ), um Daten aus der dritten Tabelle (SpecialOfferProduct) zu lesen, sogar das SELECT/WHERE -Klauseln enthält keine Spalten aus dieser Tabelle und der FK-Einschränkung (FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID) wird (ebenfalls) vertraut. Dies geschieht, weil dieser letzte FK mehrspaltig ist.

Anmerkung 2 / Ansicht 2: Was ist, wenn wir die gelesene Datei entfernen möchten (Scan /Seek ) auf Sales.SpecialOfferProduct ? Dieser zweite FK ist mehrspaltig und in solchen Fällen kann der SQL Server den FK nicht eliminieren (siehe vorherigen Blogbeitrag von Conor Cunnigham). In diesem Fall müssen wir das INNER JOIN Sales.SpecialOfferProduct ersetzen mit LEFT OUTER JOIN Sales.SpecialOfferProduct um die FK-Eliminierung zu erreichen. Sowohl SpecialOfferID und ProductID Spalten sind NOT NULL und wir haben einen vertrauenswürdigen FK, der auf SpecialOfferProduct verweist Tabelle.