Korrelierte Unterabfrage und Join: Immer noch der gleiche Ausführungsplan?

7

Ich habe eine korrelierte Unterabfrage wie diese (von BOL ):

SELECT DISTINCT c.LastName, c.FirstName, e.BusinessEntityID 
FROM Person.Person AS c JOIN HumanResources.Employee AS e
ON e.BusinessEntityID = c.BusinessEntityID 
WHERE 5000.00 IN
    (SELECT Bonus
    FROM Sales.SalesPerson sp
    WHERE e.BusinessEntityID = sp.BusinessEntityID) ;
GO

Wenn ich diese Abfrage mit Joins umschreibe

select c.LastName, c.FirstName, e.BusinessEntityID, d.Bonus
from Person.Person as c 
    inner join HumanResources.Employee as e on e.BusinessEntityID = c.BusinessEntityID
    inner join Sales.SalesPerson as d on d.BusinessEntityID = c.BusinessEntityID
where Bonus = 5000.00

Und schauen Sie sich den tatsächlichen Ausführungsplan an, er sieht in beiden Abfragen genauso aus. Warum? Ich dachte, dass die korrelierte Unterabfrage aufgrund der verschachtelten Schleife viel langsamer ist und der Ausführungsplan anders aussieht. Liegt es daran, dass diese Tabellen nicht viele Daten enthalten?

jrara
quelle
Ja, aber warum liefern sie den gleichen Ausführungsplan?
Jrara
2
Weil der Optimierer intelligent genug ist, um die Situation zu erkennen. Es ist nicht ungewöhnlich, dass (zusammengehörige) Unterauswahlen und Verknüpfungen nach Möglichkeit denselben Plan ergeben.
a_horse_with_no_name
Bitte geben Sie die EXPLAIN-Ausgabe der Original- und Rewrite-SQLs an.
@Aftab Bitte poste keine weiteren Kommentare als Antworten. Wir haben eine Kommentarfunktion aus einem bestimmten Grund.
JNK
2
@Aftab: Diese Frage ist markiert mit [sql-server], nicht [mysql].
Ypercubeᵀᴹ

Antworten:

11

Die beiden Abfragen sind logisch identisch und erzeugen denselben Plan. Die Vereinfachungsphase des Abfrageoptimierers übernimmt dies.

Sie sind aufgrund der Einschränkungen in den Tabellen identisch - Fremdschlüssel, Eindeutigkeit, Nullfähigkeit ...

Rob Farley
quelle
5

Ein guter Optimierer erkennt, wann eine korrelierte Abfrage als Join geschrieben worden sein könnte, und verwendet denselben Plan. Viele korrelierte Abfragen können genauso einfach geschrieben werden wie ein Join. In diesem Fall erledigt der Optimierer seine Arbeit. Die Optimierung der Abfrage auf diese Weise ermöglicht Pläne, die mit der korrelierten Abfrage keinen Sinn ergeben würden.

Ich neige dazu, eine korrelierte Abfrage zu schreiben, wenn dies semantisch sinnvoll ist, und einen Join zu verwenden, wenn dies semantisch angemessen ist. Moderne Optimierer generieren die entsprechende Abfrage. Wenn sich die Optimierer verbessern, schreibe ich Fragen zur Verständlichkeit und versuche nicht, den Optimierer zu erraten. (Ich finde, dass der Optimierer normalerweise besser abschneidet als ich. In seltenen Fällen weiß ich etwas, das der Optimierer anhand der Abfrage nicht ermitteln kann.)

BillThor
quelle