it-swarm.com.de

CROSS APPLY vs OUTER APPLY Geschwindigkeitsdifferenz

Ich habe CROSS APPLY verwendet, um Benutzer- und GeoPhone-Tabellen zu verbinden, und alles hat schnell funktioniert, aber jetzt habe ich Benutzer mit NULL-Werten in der Telefonspalte. Cross Apply überspringt diese Zeilen in der endgültigen Ausgabe. Also bin ich auf OUTER APPLY umgestiegen. Es arbeitet jedoch wesentlich langsamer (mehr als 15-mal langsamer, wenn die Gesamtanzahl der ausgegebenen Zeilen nur um 1000 erhöht wird).

SELECT TOP (10000) dbo.Users.Login, dbo.Users.Phone, GeoPhone.Country
FROM  dbo.Users CROSS APPLY
                 (SELECT TOP 1 Country
                 FROM    dbo.GeoPhone
                 WHERE dbo.Users.Phone <= dbo.GeoPhone.[End]) GeoPhone

Gegen:

SELECT TOP (10000) dbo.Users.Login, dbo.Users.Phone, GeoPhone.Country
FROM  dbo.Users OUTER APPLY
                 (SELECT TOP 1 Country
                 FROM    dbo.GeoPhone
                 WHERE dbo.Users.Phone <= dbo.GeoPhone.[End]) GeoPhone

Ich versuche zu verstehen warum. Wie ich sehe, ist der Ausführungsplan anders. Aber theoretisch sehe ich keine Berechnung, die eine solche Verlangsamung verursachen könnte.

Irgendwelche Ideen?

MEINE LÖSUNG:

SELECT TOP (10000) dbo.Users.Login, dbo.Users.Phone, GeoPhone.Country
FROM  dbo.Users CROSS APPLY
                 (SELECT TOP 1 Country
                 FROM    dbo.GeoPhone
                 WHERE ISNULL(dbo.Users.Phone, 0) <= dbo.GeoPhone.[End]) GeoPhone

Dadurch wird das tatsächliche Land für Nicht-Null-Telefone und das Land aus dem ersten Bereich für Null-Telefone zugewiesen (was für meinen Fall bereits "UNBEKANNT" ist). Aus irgendeinem Grund WHERE dbo.Users.Phone <= dbo.GeoPhone.[End] OR dbo.Users.Phone IS NULL führt zu den gleichen Ergebnissen, jedoch wesentlich langsamer.

Bitte zögern Sie nicht, dies zu kommentieren.

51
Denis

CROSS APPLY ist MSSQL-spezifisch ... Microsoft bei APPLY

APPLY bewirkt, dass die rechte Abfrage einmal pro Ergebnis in der linken Abfrage ausgeführt wird. CROSS berücksichtigt nur übereinstimmende Zeilen wie INNER JOIN. Bei Verwendung von OUTER werden alle Zeilen in der Abfrage auf der linken Seite berücksichtigt. Die zusätzlichen Reihen taten weh.

Ich empfehle Ihnen, Ihre rechte Abfrage neu zu formulieren, um NULL explizit zu akzeptieren, anstatt OUTER APPLY zu verwenden.

73
Magicianeer

Sie können dies versuchen:

SELECT TOP (10000) dbo.Users.Login, dbo.Users.Phone, GeoPhone.Country
FROM  dbo.Users CROSS APPLY
                 (SELECT TOP 1 Country
                 FROM    dbo.GeoPhone
                 WHERE dbo.Users.Phone <= dbo.GeoPhone.[End]) GeoPhone
UNION ALL
SELECT TOP (10000) dbo.Users.Login, dbo.Users.Phone, NULL AS Country
FROM  dbo.Users
WHERE dbo.Users.Phone IS NULL

Stellen Sie sicher, dass Sie einen Index für dbo.Users.Phone haben

11
A-K