鉴于观点
create view MyView as
select Id, ExpensiveFunction(Name) as Expr from MyTable
如果在查询中使用
select *
from AnotherTable a
inner join MyView b on b.Id = a.Id
ExpensiveFunction
中的每一行都计算MyTable
,或者SQL Server是否足够智能以先加入AnotherTable
,然后仅针对已过滤的行调用ExpensiveFunction
?
如果MyView
是子查询或TVF,它会有不同的行为吗?
答案 0 :(得分:0)
ExpensiveFunction
。如果您的最终选择语句甚至根本不包括它,那么该函数将不会被调用。
类似地,如果最终选择仅选择表的十分之一,则该函数将仅在该十分之一上调用。
这在子查询和内联视图中的工作方式相同。您可以为子查询中的字段指定函数,如果从未使用该字段,则永远不会执行该函数。
标量函数确实非常昂贵。 可能可以通过使用表值函数来减少开销:
SELECT
MyTable.*,
ExpensiveFunction.Value
FROM
MyTable
CROSS APPLY
MyFunction(MyTable.field1, MyTable.field2) as ExpensiveFunction
如果ExpensiveFunction
是一个内联(即非多语句)函数,并且它只返回一行,它通常会比标量函数更好地扩展。
如果使用返回多行的多语句表值函数,将为每一行调用ExpensiveFunction
。但一般情况下,您不应该让TVF返回稍后会被丢弃的记录。
内联函数,因为它们可以内联扩展,就好像它们是SQL宏一样,只会在必要时调用ExpensiveFunction
,就像视图一样。
在您的问题示例中,只应在必要时调用 ExpensiveFunction
。但是,您肯定应该查看查询执行计划并使用SQL事件探查器来优化性能。