Esta no es una respuesta canónica, pero noté que para los planes de consulta de bucles anidados que se muestran en el Fiddle de SQL, era posible aplicar el plan de la Consulta 2 a la Consulta 1 con el uso de la USE PLAN
sugerencia, pero al intentar la operación inversa falla con
El procesador de consultas no pudo generar un plan de consulta porque la sugerencia USE PLAN contiene un plan que no pudo verificarse como legal para la consulta. Retire o reemplace la sugerencia de PLAN DE USO Para una mayor probabilidad de forzar un plan exitoso, verifique que el plan provisto en la sugerencia USE PLAN es uno generado automáticamente por SQL Server para la misma consulta.
La desactivación de la regla de transformación del optimizador ReorderLOJN
evita que la sugerencia de plan previamente exitosa también tenga éxito.
Experimentar con mayores cantidades de datos muestra que SQL Server ciertamente también es capaz de transformarse (A LOJ B) LOJ C
de A LOJ (B LOJ C)
forma natural, pero no vi ninguna evidencia de que lo contrario sea cierto.
Un caso muy artificial en el que la primera consulta funciona mejor que la segunda es
DROP TABLE MyGrandChild , MyChild, MyParent
CREATE TABLE MyParent
(Id int)
CREATE TABLE MyChild
(Id int PRIMARY KEY
,ParentId int,
Filler char(8000) NULL)
CREATE TABLE MyGrandChild
(Id int
,ParentId int)
INSERT INTO MyChild
(Id, ParentId)
SELECT TOP (100000) ROW_NUMBER() OVER (ORDER BY @@SPID),
ROW_NUMBER() OVER (ORDER BY @@SPID)
FROM master..spt_values v1, master..spt_values
INSERT INTO MyGrandChild
(Id, ParentId)
OUTPUT INSERTED.Id INTO MyParent
SELECT TOP (3000) Id, Id AS ParentId
FROM MyChild
ORDER BY Id
SET STATISTICS IO ON;
SET STATISTICS TIME ON;
SELECT gc.Id AS gcId,
gc.ParentId AS gcpId,
c.Id AS cId,
c.ParentId AS cpId,
p.Id AS pId
FROM MyGrandChild AS gc
LEFT OUTER JOIN MyChild AS c
ON c.[Id] = gc.[ParentId]
LEFT OUTER JOIN MyParent AS p
ON p.[Id] = c.[ParentId]
SELECT gc.Id AS gcId,
gc.ParentId AS gcpId,
c.Id AS cId,
c.ParentId AS cpId,
p.Id AS pId
FROM MyGrandChild AS gc
LEFT OUTER JOIN( MyChild AS c
LEFT OUTER JOIN MyParent AS p
ON p.[Id] = c.[ParentId])
ON c.[Id] = gc.[ParentId]
Que da planes
Para mí, la Consulta 1 tuvo un tiempo transcurrido de 108 ms frente a 1,163 ms para la Consulta 2.
Consulta 1
Table 'Worktable'. Scan count 0, logical reads 0
Table 'MyChild'. Scan count 0, logical reads 9196
Table 'MyGrandChild'. Scan count 1, logical reads 7
Table 'MyParent'. Scan count 1, logical reads 5
Consulta 2
Table 'MyParent'. Scan count 1, logical reads 15000
Table 'MyChild'. Scan count 0, logical reads 9000
Table 'MyGrandChild'. Scan count 1, logical reads 7
Por lo tanto, se puede suponer provisionalmente que la primera sintaxis ("no verificada") es potencialmente beneficiosa, ya que permite que se consideren más órdenes de unión potenciales, pero no he realizado pruebas lo suficientemente exhaustivas como para tener mucha confianza en esto como regla general.
Es muy posible que se presenten ejemplos contrarios en los que la consulta 2 funcione mejor. Pruebe ambos y mire los planes de ejecución.