Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Diferença de desempenho entre a junção esquerda e a junção interna


Há pelo menos um caso em que LEFT [OUTER] JOIN é uma opção melhor que [INNER] JOIN . Eu falo sobre obter os mesmos resultados usando OUTER em vez de INNER .

Exemplo (estou usando o banco de dados 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;

Resultados da primeira consulta:
is_not_trusted name
-------------- ---------------------------------------------------------------
0              FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID
0              FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID

Planos de execução para as duas últimas consultas:

Observação 1/Visualização 1: Se olharmos para o plano de execução para SELECT SalesOrderDetailID FROM View1 vemos um Eliminação FK porque o FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID restrição é confiável e tem uma única coluna. Mas, o servidor é forçado (por causa de INNER JOIN Sales.SpecialOfferProduct ) para ler dados da terceira tabela (SpecialOfferProduct) até mesmo o SELECT/WHERE cláusulas não contém nenhuma coluna desta tabela e a restrição FK (FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID) é (também) confiável. Isso acontece porque este último FK é multicoluna.

Observação 2 / Visualização 2: E se quisermos remover a leitura (Scan /Seek ) no Sales.SpecialOfferProduct ? Este segundo FK é multicoluna e, para esses casos, o SQL Server não pode eliminar o FK (consulte a postagem anterior no blog de Conor Cunnigham). Nesse caso, precisamos substituir o INNER JOIN Sales.SpecialOfferProduct com LEFT OUTER JOIN Sales.SpecialOfferProduct para obter a eliminação FK. Ambos SpecialOfferID e ProductID colunas são NOT NULL e temos um FK confiável referenciando SpecialOfferProduct tabela.