让我们假设我有一个观点,如下:
CREATE VIEW EmployeeView
AS
SELECT ID, Name, Salary(PaymentPlanID) AS Payment
FROM Employees
用户定义的函数Salary
有点贵。
如果我想做这样的事情,
SELECT *
FROM TempWorkers t
INNER JOIN EmployeeView e ON t.ID = e.ID
Salary
的每一行都会执行Employees
,还是会先进行连接,然后才会对连接过滤的行进行调用?如果EmployeeView
是子查询或表值函数而不是视图,我可以期待相同的行为吗?
答案 0 :(得分:4)
该功能仅在相关时调用。如果您的最终选择语句不包含该字段,则根本不会调用它。如果你的最终选择指的是你表的1%,那么只会为表的1%调用它。
对于子查询/内联视图,这实际上是相同的。您可以为子查询中的字段指定函数,然后从不使用该字段,在这种情况下,函数永远不会被调用。
顺便说一句:在许多方面,标量函数确实非常昂贵。您可能能够通过将其形成为内联表值函数来降低其成本。
SELECT
myTable.*,
myFunction.Value
FROM
myTable
CROSS APPLY
myFunction(myTable.field1, myTable.field2) as myFunction
只要MyFunction是Inline(不是多语句)并且每组输入只返回一行,这通常比标量函数更好地扩展。
这与使整个视图成为表值函数略有不同,它返回许多行。
如果这样的TVF是多方的,它将为每条记录调用Salary函数。但是内联函数可以内联扩展,就像SQL宏一样,因此只需要根据需要调用Salary;喜欢这个观点。
作为TVF的一般规则,不要返回将被丢弃的记录。
答案 1 :(得分:1)
它应该只对连接的行执行Salary函数。但是你没有进一步过滤表格。如果ID是外键列而不是null,那么它将为所有行执行该函数。 实际执行计划是一个值得肯定的好地方。
答案 2 :(得分:0)
如上所述,只会为相关行调用该函数。对于您的进一步问题,并且 非常了解正在发生的事情 ,您需要通过SQL事件探查器或通过查看实际执行计划并过去来收集性能数据倍。然后测试一些理论并找出哪种理论是最佳的。