Se dai un'occhiata ai 2 piani di esecuzione, c'è una risposta facile a quale è meglio? Non ho intenzionalmente creato indici, quindi è più facile vedere cosa sta succedendo.
Il secondo piano ha un costo stimato inferiore, quindi in questo senso limitato è "migliore".
I set di dati sono così piccoli che l'ottimizzatore non ha trascorso molto tempo a cercare alternative. La prima forma della query capita di trovare un piano usando hash join e uno spool di tabella all'inizio. Il costo stimato di quel piano è così basso che l'ottimizzatore non si preoccupa di cercare qualcosa di meglio.
La seconda forma della query capita di trovare un piano usando solo loop nidificati join esterni all'inizio del processo di ricerca, e di nuovo l'ottimizzatore decide che il piano è abbastanza buono. Accade così che si stima che questo piano sia più economico.
Detto questo (come menzionato nei commenti alle domande) le due query non sono semanticamente identiche. Questo potrebbe non essere importante per te se puoi garantire che i risultati saranno sempre gli stessi per tutti i possibili stati futuri del tuo database, ma l'ottimizzatore non può fare questo presupposto. Produce sempre e solo piani che sono garantiti per produrre gli stessi risultati specificati da SQL, in ogni circostanza.
Mi sono reso conto che la sintassi nidificata modifica anche il comportamento della query.
La "sintassi nidificata" è solo un aspetto dell'intera specifica della sintassi del join ANSI. Per abilitare una specifica logica completa per modelli di join più complessi, la specifica consente parentesi (opzionali) e FROM
sottoquery di clausole.
La query può essere scritta usando la stessa sintassi ANSI usando le parentesi:
SELECT
A.*,
M.*,
N.*
FROM dbo.Autos AS A
LEFT JOIN
(
dbo.Manufacturers AS N
JOIN dbo.Models AS M
ON M.ManufacturerID = N.ManufacturerID
) ON M.ModelID = A.ModelID;
Questa forma mostra chiaramente che il requisito logico è aderire sinistra dal Autos
al risultato di interni unirsi Manufacturers
a Models
. Omettendo le parentesi opzionali si ottiene il modulo che si chiama 'nidificato':
SELECT
A.*,
M.*,
N.*
FROM dbo.Autos AS A
LEFT JOIN dbo.Manufacturers AS N
JOIN dbo.Models AS M
ON M.ManufacturerID = N.ManufacturerID
ON M.ModelID = A.ModelID;
Questa non è una sintassi diversa: sta semplicemente omettendo le parentesi opzionali e riformattando un po '.
Come menzionato Martin, in questo caso è anche possibile esprimere il requisito logico usando i join interni seguiti da un join esterno destro:
SELECT
A.*,
M.*,
N.*
FROM dbo.Manufacturers AS N
JOIN dbo.Models AS M
ON M.ManufacturerID = N.ManufacturerID
RIGHT JOIN dbo.Autos AS A
ON A.ModelID = M.ModelID;
Tutti e tre i moduli di query sopra utilizzano la stessa sintassi di join ANSI. Inoltre, tutti e tre producono lo stesso piano di esecuzione fisica con il set di dati fornito:
Come ho detto nella mia risposta alla tua domanda precedente, le query che esprimono esattamente lo stesso requisito logico non produrranno sempre lo stesso piano di esecuzione. Quale modulo di query logica preferisci utilizzare è in gran parte una questione di stile. Non esiste alcuna correlazione tra uno stile particolare e piani di query "migliori" in generale. In generale, sconsiglioi di riscrivere una query per ottenere un piano particolare se la nuova query non fosse autenticamente logicamente identica all'originale.
Lo standard SQL consente anche le FROM
subquery di clausole, quindi un altro modo per scrivere la stessa specifica di query è:
SELECT *
FROM dbo.Autos AS A
LEFT JOIN
(
SELECT
N.ManufacturerID,
ManufacturerName = N.Name,
M.ModelID,
ModelName = M.Name
FROM dbo.Manufacturers AS N
JOIN dbo.Models AS M
ON M.ManufacturerID = N.ManufacturerID
) AS R1
ON R1.ModelID = A.ModelID;
Usando la sintassi tradizionale, dobbiamo cambiare il join in `Produttori in un join esterno, in questo modo ... ma questo cambia il piano di query.
Ciò probabilmente modifica il significato della query, nel qual caso non è tecnicamente un'alternativa valida (ma vedi il commento di ypercube sulla tua domanda).
Le parentesi (facoltative) nella sintassi del join ANSI sono lì proprio per requisiti di join più complessi come questo, quindi non dovresti aver paura di usarli dove necessario.