sql >> Base de Datos >  >> RDS >> Sqlserver

Diferencia de rendimiento entre la combinación izquierda y la combinación interna

Hay al menos un caso en el que LEFT [OUTER] JOIN es una mejor opción que [INNER] JOIN . Hablo de obtener los mismos resultados usando OUTER en lugar de INNER .

Ejemplo (estoy usando base de datos 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 de la primera consulta:

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

Planes de ejecución para las dos últimas consultas:

Nota 1 / Vista 1: Si observamos el plan de ejecución para SELECT SalesOrderDetailID FROM View1 vemos un Eliminación de FK porque el FK_SalesOrderDetail_SalesOrderHeader_SalesOrderID la restricción es de confianza y tiene una sola columna. Pero, el servidor es forzado (debido a INNER JOIN Sales.SpecialOfferProduct ) para leer datos de la tercera tabla (SpecialOfferProduct) incluso el SELECT/WHERE cláusulas no contiene ninguna columna de esta tabla y la restricción FK (FK_SalesOrderDetail_SpecialOfferProduct_SpecialOfferIDProductID) es (también) de confianza. Esto sucede porque este último FK es de varias columnas.

Nota 2 / Vista 2: ¿Qué sucede si queremos eliminar la lectura (Scan /Seek ) en Sales.SpecialOfferProduct ? Este segundo FK es de varias columnas y, en tales casos, SQL Server no puede eliminar el FK (consulte la publicación anterior del blog de Conor Cunnigham). En este caso, debemos reemplazar el INNER JOIN Sales.SpecialOfferProduct con LEFT OUTER JOIN Sales.SpecialOfferProduct para conseguir la eliminación de FK. Ambos SpecialOfferID y ProductID las columnas son NOT NULL y tenemos un FK de confianza que hace referencia a SpecialOfferProduct mesa.