Có ít nhất một trường hợp LEFT [OUTER] JOIN
là một lựa chọn tốt hơn [INNER] JOIN
. Tôi nói về việc đạt được kết quả tương tự bằng cách sử dụng OUTER
thay vì INNER
.
Ví dụ (Tôi đang sử dụng cơ sở dữ liệu 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;
Kết quả cho truy vấn đầu tiên:
is_not_trusted name
-------------- ---------------------------------------------------------------
0 FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID
0 FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID
Kế hoạch thực thi cho hai truy vấn cuối cùng:
Lưu ý 1 / Chế độ xem 1: Nếu chúng ta xem xét kế hoạch thực thi cho SELECT SalesOrderDetailID FROM View1
chúng tôi thấy Loại bỏ FK
bởi vì FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID
ràng buộc được tin cậy và nó có một cột duy nhất. Tuy nhiên, máy chủ bị ép buộc (vì INNER JOIN Sales.SpecialOfferProduct
) để đọc dữ liệu từ bảng thứ ba (SpecialOfferProduct) ngay cả SELECT/WHERE
mệnh đề không chứa bất kỳ cột nào từ bảng này và ràng buộc FK (FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID) (cũng) được tin cậy. Điều này xảy ra vì FK cuối cùng này là nhiều cột.
Lưu ý 2 / Chế độ xem 2: Điều gì xảy ra nếu chúng ta muốn xóa nội dung đã đọc (Scan
/ Seek
) trên Sales.SpecialOfferProduct
? FK thứ hai này là đa cột và trong những trường hợp như vậy, Máy chủ SQL không thể loại bỏ FK (xem bài đăng trên blog Conor Cunnigham trước đó). Trong trường hợp này, chúng tôi cần thay thế INNER JOIN Sales.SpecialOfferProduct
với LEFT OUTER JOIN Sales.SpecialOfferProduct
để loại bỏ FK. Cả SpecialOfferID
và ProductID
các cột NOT NULL
và chúng tôi có tham chiếu FK đáng tin cậy SpecialOfferProduct
bảng.