查询执行顺序/优化

时间:2011-09-22 19:33:59

标签: sql-server sql-server-2005

鉴于观点

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,它会有不同的行为吗?

1 个答案:

答案 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事件探查器来优化性能。