No advantage of using Cross Apply or CTE over inline sub-query
-
28-09-2020 - |
Question
I came across a query like this:
SELECT (SELECT COUNT(1) FROM Orders o WHERE i.ItemId = o.ItemId) [C]
FROM Items i
I changed it to following
;WITH cte_count
AS
(
SELECT COUNT(1) c, OrderId FROM Orders Group By ItemId
)
SELECT a.c [Count], i.Name
FROM Items i
INNER JOIN cte_count c ON (c.ItemId = i.ItemId)
But the execution plan for both is same as shown below:
Similarly there was another query selecting TOP 1 Order By Id
. I tried moving this one to CROSS APPLY
But for this one as well I got same execution plans.
Of course there were other joins and columns in query.
My dilemma is about utility and advantages of using CROSS APPLY
and CTE
. Are there any or its just exotic?
Solution
But the execution plan for both is same as shown below:
The plans are different. One is an inner join, the other is an outer join. The results may be the same in your simple test, but the semantics are different. In more complex queries, the difference may cause more obviously different execution plans, and come with a performance impact.
There are usually many ways to express the same requirement (or similar requirement, as in your example) in SQL. Which you use is initially a question of preference and style. In some cases, using one or the other will produce important performance differences because the declarative SQL takes a different code path through the optimizer. In this particular case, the outer join may play less well with the optimizer's exploration abilities (it has fewer tools to use with outer joins than inner joins).
Rewriting a query to define the same results using different syntax can be a valid tuning method, but it requires careful attention to detail and retesting whenever SQL Server is patched or upgraded. There is generally no reason to prefer one way of expressing a requirement in SQL over another.
In addition, as Andriy mentioned in a comment on the other copy of your question, "in the more general case, your inline queries will give you only one result per row, while joining to a CTE (which doesn't have to be a CTE, it could be a normal subselect) or CROSS APPLYing a row set can give you access to more than one column."
OTHER TIPS
My dilemma is about utility and advantages of using CROSS APPLY and CTE. Are there any or its just exotic?
For small datasets the optimizer is probably not bothering with extensive analysis. However, if one were to look at competing plans for large data sets (say millions of Orders or Items from your example), then CROSS APPLY, especially if Items are indexed, would execute quicker.
Moreover is this even appropriate to check it like this, using execution plan.
Sure. If there was a difference to be had, the plans would have shown. Moreover you would definitely notice performance differences upon execution.
What if you do
SELECT i.Name
COUNT(o.OrderId) c
FROM Items i
JOIN Orders o ON i.ItemID = o.ItemID
GROUP BY i.ItemID
cte
and apply
has it's advantages in some cases i'm sure, just probably not simple cases like this
I like to use a cte
mostly for aesthetic reasons when i'm trying to create a visual flow of how i'm breaking down larger results into smaller ones, for building the final query, and recursion ofcourse.
apply
is pretty cool when you're using a table value function that takes a param value from the previous table. cross apply
can be prettier than a full join
statement.
if you know what you're looking for in a query plan it's just a matter of preference i suppose