Given the view
create view MyView as
select Id, ExpensiveFunction(Name) as Expr from MyTable
If used in the query
select *
from AnotherTable a
inner join MyView b on b.Id = a.Id
Is ExpensiveFunction computed for every row in MyTable, or is SQL Server smart enough to join to AnotherTable first, and then call ExpensiveFunction for only the filtered rows?
Would it behave differently if MyView is a subquery or TVF?
ExpensiveFunctionwill only be called when it is relevant. If your final select statement does not even include it at all, the function will, in turn, not be called.Similarly, if the final select only selects one tenth of the table, the function will only be called on that one tenth.
This works the same way in sub-queries and inline views. You could specify a function for a field in a sub-query, and if the field is never used, the function will never be executed.
It is true that scalar functions are notoriously expensive. It might be possible to reduce the overhead by instead using a table valued function:
Provided that
ExpensiveFunctionis an inline (i.e. not multi-statement) function, and that it only returns one row, it will usually scale better than scalar functions do.If you use a multi-statement table valued function that returns multiple rows, it will call
ExpensiveFunctionfor every row. Generally, though, you shouldn’t have TVFs that return records that will later be discarded.Inline functions, on the other hand, since they can be expanded inline, as if they were a SQL macro, will only call
ExpensiveFunctionwhen necessary, like the view.In the example in your question,
ExpensiveFunctionshould only be called when necessary. To be sure, though, you should definitely look at your query execution plan and use an SQL profiler to optimize performance.