Er is ten minste één geval waarin LEFT [OUTER] JOIN
is een betere optie dan [INNER] JOIN
. Ik heb het over het verkrijgen van dezelfde resultaten met OUTER
in plaats van INNER
.
Voorbeeld (ik gebruik AdventureWorks 2008-database ):
-- 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;
Resultaten voor de eerste zoekopdracht:
is_not_trusted name
-------------- ---------------------------------------------------------------
0 FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID
0 FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID
Uitvoeringsplannen voor de laatste twee query's:
Opmerking 1 / Weergave 1: Als we kijken naar het uitvoeringsplan voor SELECT SalesOrderDetailID FROM View1
we zien een FK-eliminatie
omdat de FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID
beperking is vertrouwd en heeft een enkele kolom. Maar de server wordt geforceerd (vanwege INNER JOIN Sales.SpecialOfferProduct
) om gegevens uit de derde tabel (SpecialOfferProduct) te lezen, zelfs de SELECT/WHERE
clausules bevat geen kolommen uit deze tabel en de FK-beperking (FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID) is (ook) vertrouwd. Dit gebeurt omdat deze laatste FK uit meerdere kolommen bestaat.
Opmerking 2 / Weergave 2: Wat als we de gelezen (Scan
/Seek
) op het Sales.SpecialOfferProduct
? Deze tweede FK is multicolumn en in dergelijke gevallen kan de SQL Server de FK niet elimineren (zie vorige Conor Cunnigham blogpost). In dit geval moeten we de INNER JOIN Sales.SpecialOfferProduct
. vervangen met LEFT OUTER JOIN Sales.SpecialOfferProduct
om FK eliminatie te krijgen. Beide SpecialOfferID
en ProductID
kolommen zijn NOT NULL
en we hebben een vertrouwde FK die verwijst naar SpecialOfferProduct
tafel.