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 开发者_Python百科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?
ExpensiveFunction
will 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:
SELECT
MyTable.*,
ExpensiveFunction.Value
FROM
MyTable
CROSS APPLY
MyFunction(MyTable.field1, MyTable.field2) as ExpensiveFunction
Provided that ExpensiveFunction
is 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 ExpensiveFunction
for 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 ExpensiveFunction
when necessary, like the view.
In the example in your question, ExpensiveFunction
should 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.
精彩评论