I was using CROSS APPLY to join Users and GeoPhone tables and everything worked fast but now I have Users with NULL values in Phone column. Cross apply skips these rows in final output. So I switched to OUTER APPLY. But it works greatly slower (more than 15 times as slower when total number of rows in output increased just by 1000).
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
Versus:
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
I'm trying to understand why. As I see execution plan is different. But theoretically I can't see any computation that may cause such slowdown.
Any ideas?
MY FINAL SOLUTION:
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
This assigns actual Country for non-null phones and country from first range for null phones (which is "UNKNOWN" for my case already). For some reason WHERE dbo.Users.Phone <= dbo.GeoPhone.[End] OR dbo.Users.Phone IS NULL
does the same results but greatly slower.
Please feel free to comment this out.
So you might conclude, the CROSS APPLY is equivalent to an INNER JOIN (or to be more precise its like a CROSS JOIN with a correlated sub-query) with an implicit join condition of 1=1 whereas the OUTER APPLY is equivalent to a LEFT OUTER JOIN.
While most queries which employ CROSS APPLY can be rewritten using an INNER JOIN , CROSS APPLY can yield better execution plan and better performance, since it can limit the set being joined yet before the join occurs.
In simple terms, a join relies on self-sufficient sets of data, i.e. sets should not depend on each other. On the other hand, CROSS APPLY is only based on one predefined set and can be used with another separately created set. A worked example should help with understanding this difference.
CROSS JOIN is simply Cartesian Product of two tables, irrespective of any filter criteria or any condition. FULL OUTER JOIN gives unique result set of LEFT OUTER JOIN and RIGHT OUTER JOIN of two tables. It also needs ON clause to map two columns of tables.
CROSS APPLY is MSSQL-specific... Microsoft on APPLY
APPLY causes the right-side query to execute once per result in the left-side query. CROSS only considers matching rows like INNER JOIN. Using OUTER considers all rows in left-side query. The extra rows hurt.
I recommend you reformulate your right-side query to explicitly accept NULLs instead of using OUTER APPLY.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With