CROSS APPLY vs OUTER APPLY speed difference
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.
CROSS APPLY performance difference
Found it.
To force the CROSS APPLY to run on the sub set of results from the JOINs and not on the whole table before the JOINS I used OPTION (FORCE ORDER)
SELECT
b.BrandId,
b.Name,
ah.Type,
c.ContactEmails,
c.ContactNumbers,
c.ContactLinks
FROM
@IdsToFilterBy ids
JOIN dbo.AccountHandler ah ON ah.AccountHandlerId = ids.Id
JOIN dbo.Brand b ON ah.RepresentedByBrandId = b.BrandId
CROSS APPLY dbo.[fn_GetBrandContactDetails](b.BrandId) AS c
OPTION (FORCE ORDER)
This now runs instantly and looking at the execution plan the function is only being called for the one result and not the whole db table.
When should I use CROSS APPLY over INNER JOIN?
Can anyone give me a good example of when CROSS APPLY makes a difference in those cases where INNER JOIN will work as well?
See the article in my blog for detailed performance comparison:
INNER JOIN
vs.CROSS APPLY
CROSS APPLY
works better on things that have no simple JOIN
condition.
This one selects 3
last records from t2
for each record from t1
:
SELECT t1.*, t2o.*
FROM t1
CROSS APPLY
(
SELECT TOP 3 *
FROM t2
WHERE t2.t1_id = t1.id
ORDER BY
t2.rank DESC
) t2o
It cannot be easily formulated with an INNER JOIN
condition.
You could probably do something like that using CTE
's and window function:
WITH t2o AS
(
SELECT t2.*, ROW_NUMBER() OVER (PARTITION BY t1_id ORDER BY rank) AS rn
FROM t2
)
SELECT t1.*, t2o.*
FROM t1
INNER JOIN
t2o
ON t2o.t1_id = t1.id
AND t2o.rn <= 3
, but this is less readable and probably less efficient.
Update:
Just checked.
master
is a table of about 20,000,000
records with a PRIMARY KEY
on id
.
This query:
WITH q AS
(
SELECT *, ROW_NUMBER() OVER (ORDER BY id) AS rn
FROM master
),
t AS
(
SELECT 1 AS id
UNION ALL
SELECT 2
)
SELECT *
FROM t
JOIN q
ON q.rn <= t.id
runs for almost 30
seconds, while this one:
WITH t AS
(
SELECT 1 AS id
UNION ALL
SELECT 2
)
SELECT *
FROM t
CROSS APPLY
(
SELECT TOP (t.id) m.*
FROM master m
ORDER BY
id
) q
is instant.
Benefits of INNER JOIN over CROSS APPLY
You can always use a CROSS APPLY
where you'd use an INNER JOIN
. But there are reasons you might (and often will) prefer INNER JOIN
.
In case the two are equivalent the SQL Server optimizer does not treat them differently in my experience. Therefore, I do not follow the suggestion that a CROSS APPLY
is faster. If apples are compared to apples the performance is, in all the query plans I have seen, identical.
INNER JOIN
is more convenient to write. Also, it is idiomatic. Therefore, it is most legible and maintainable. INNER JOIN
also is more widely supported although that probably does not matter on SQL Server. I also estimate that many developers simply do not know CROSS APPLY
.
Why cross apply is faster than inner join?
CROSS APPLY is meant to be used with functions and tables that return result based on parameters.
So, the fact you querying function is the reason why "CROSS APPLY" is faster.
INNER JOIN vs CROSS JOIN vs CROSS APPLY
The first two are equivalent. Whether you use an inner join or cross join is really a matter of preference in this case. I think I would typically use the cross join
, because there is no real join condition between the tables.
Note: You should never use cross join
when the intention is a "real" inner join
that has matching conditions between the tables.
The cross apply
is not doing the same thing. It is only choosing one row. If your intention is to get at most one matching row, then use cross apply
. If the intention is to get exactly one matching row, then use outer apply
.
UNION vs CROSS APPLY performance
Firs query have high IO cost and low CPU cost than second query. second query have low IO and more CPU than first query.
I suggest that use second query, because IO have more affect in performance than CPU. if you can reduce IO of your query and increase CPU cost is better that reduce CPU cost and increase IO cost.
CROSS APPLY Style versus Performance
If there is a performance disadvantage it must be in the compilation stage of query execution. As execution plans are cached the second the time query executes there will be no performance penalty.
SQL Server can see through the CROSS APPLYs and convert them to simple, stacked "compute scalars".
Another potential problem might be the size of the query. Not sure if there are any relevant limitations in terms of number of AST-nodes or joins or so (I guess CROSS APPLY counts as a join when it comes to internal limits).
Apart from these problems I think that CROSS APPLYs are a very nice and fast solution.
Difference between cross apply and inner join based on below example
If my understanding of cross apply is correct the reason you are getting different results here is that CROSS APPLY will apply whatever comes after apply (the right operator) to every row in the left operator (#temp). This means that the number of rows in the result will be the same as the number of rows in #temp. Basing my answer off of "The table-valued function acts as the right input and the outer table expression acts as the left input. The right input is evaluated for each row from the left input and the rows produced are combined for the final output." from https://technet.microsoft.com/en-us/library/ms175156(v=sql.105).aspx.
Note that if you really wanted the results to be the same you could change your cross apply query to this:
SELECT *
FROM #temp t1
CROSS apply (SELECT Sum(col1) AS col1
FROM #temp2 t2
WHERE t1.col1 = t2.col1) A
WHERE A.col1 IS NOT NULL
Also, note that INNER JOIN is defined to be where there is a match on both sides. In your case this means that there were only 3 rows. If you had used a LEFT OUTER join instead you would have gotten the same results in this case as the CROSS APPLY.
Related Topics
Sql Query to Find Last Day of Current Month
Use a Like Statement on SQL Server Xml Datatype
How to Call Scalar Function in SQL Server 2008
If I Update a View, Will My Original Tables Get Updated
How to Generate a Permutations or Combinations of N Rows in M Columns
Joining Multiple Common Table Expressions
How to Replace Blank (Null ) Values with 0 for All Records
In SQL Server, How to Create While Loop in Select
How to Multiply All Values Within a Column with SQL Like Sum()
Oracle, Make Date Time's First Day of Its Month
What Data Can Be Stored in Varbinary Data Type of SQL Server
Get Total Row Count While Paging
How to Get The SQL String from a JPA Query Object
While Loop to Iterate Through Databases
Create a Sqlite View Where a Row Depends on The Previous Row