Ответ 1
Существует, по крайней мере, один случай, когда LEFT [OUTER] JOIN
является лучшим вариантом, чем [INNER] JOIN
. Я говорю о получении тех же результатов, используя OUTER
вместо INNER
.
Пример (я использую База данных 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;
Результаты для первого запроса:
is_not_trusted name
-------------- ---------------------------------------------------------------
0 FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID
0 FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID
Планы выполнения для двух последних запросов:
Примечание 1/Вид 1: Если мы посмотрим на план выполнения для SELECT SalesOrderDetailID FROM View1
мы видим исключение FK, потому что ограничение FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID
доверено и имеет один столбец. Но сервер вынужден (из-за INNER JOIN Sales.SpecialOfferProduct
) читать данные из третьей таблицы (SpecialOfferProduct), даже предложения SELECT/WHERE
не содержат столбцов из этой таблицы, а ограничение FK (FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID) (также) доверено, Это происходит потому, что последний FK является многоколоночным.
Примечание 2/Вид 2: Что делать, если мы хотим удалить чтение (Scan
/Seek
) на Sales.SpecialOfferProduct
? Этот второй FK является многоколоночным, и для таких случаев SQL Server не может устранить FK (см. Предыдущую запись в блоге Conor Cunnigham). В этом случае нам нужно заменить INNER JOIN Sales.SpecialOfferProduct
на LEFT OUTER JOIN Sales.SpecialOfferProduct
, чтобы получить исключение FK. Оба столбца SpecialOfferID
и ProductID
являются NOT NULL
, и мы имеем доверенную FK, ссылающуюся на таблицу SpecialOfferProduct
.